LINUX.ORG.RU

Странный результат деления

 , ,


0

0

Подскажите, если кто сталкивался похожей проблемой...

Есть код:

#include <stdio.h>

int main(int argc, char **argv)
{
	double t4;
	t4 = (double)23/10;
    printf("%f\n", t4);
	return 0;
}

Если его запустить, то результат выводится как 2.3, что логично. Однако если смотреть дебагером, то в t4 лежит 2.299999999

А т.к. мне нужно использовать в дальнейшем остаток от деления, то получается какая-то «шляпа»...

Вот более полный код (код черновой), в котором я и столкнулся с данной проблемой. Суть кода - задаем число, а на выходе получаем символьную строку разложенную по числам. Например 24 должно вернуть «4 20», 23 - «3 20», 213 - «3 10 200».

В нем получается так, если я задаю число например 24, то деление на 10 происходит нормально, а вот если 23 или 21 (не четное), то результат крайне странный.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

void speech_numbers(char *outstr, double num);

int main(void)
{
    char bufer[200];
    printf("Hello World!\n");

    speech_numbers(&bufer[0],24);

    printf("speech string: %s\n",bufer);
    return 0;
}

void speech_numbers(char *outstr, double num){
    int digit, cdigit, i;
    double t0,t1,t2,t4;
    char tbuf[100];
    cdigit = 1;
    i = 0;

    printf("test\n");

    if(num == 0){
        outstr="0.wav\0";
        printf ("zero\n");
        return;
    }

    t4 = (double)23/10;
    printf("%f\n", t4);


    while(num >= (pow(10,cdigit-1))){
        t0 = pow(10,cdigit);
        t4 = (double)num/t0;
        t1 = modf(t4,&t2)*10;
        digit=(int)t1;
        printf ("%f %f\n",t1,t2);

        sprintf(&tbuf[i],"%d ",(int)(digit*(pow(10,cdigit-1))));
        i += (cdigit+1);
        cdigit++;
    }

    tbuf[i-1] = '\0';
    sprintf(outstr,"%s",tbuf);
    printf("bufer %s\n",tbuf);
}

Если кто-то решал подобную проблему, подскажите отчего так происходит и как с этим можно бороться.


Если его запустить, то результат выводится как 2.3, что логично. Однако если смотреть дебагером, то в t4 лежит 2.299999999

IEEE754.

hateyoufeel ★★★★★
()

отчего так происходит

Оттого, что в машинной памяти числа хранятся в двоичном виде. При переводе в десятичную могут получиться такие некратные 10 некрасивые уродцы.

как с этим можно бороться.

В общем случае не нужно. Результат получается правильный с точностью до характеристик типа (т.е. одинарной, двойной точности). Бороться с этим требуется только тогда, когда вещественными числами представлены деньги или похожие единицы - есть несколько решений в виде двойного округления, но деньги хранить в вещественном виде - очень грешно и чревато.

E ★★★
()

Почему выше уже написали, в данном случае чтобы побороть достаточно не использовать double, если я правильно понял задачу (в код сильно не вникал), то числа с плавающей точной и не нужны.

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)

Охохо, тред не читал, скажи, тебя уже натыкали лицом в IEEE754?

no-such-file ★★★★★
()

Остаток от fp деления - это вообще что-то новое. Таких смешных школьников тут давненько не было.

anonymous
()

У тебя ж целые числа - вот и работай с целыми. Остаток от деления в сях - оператор %.

Kiborg ★★★
()
Ответ на: комментарий от nanoolinux

Ты вообще о чем? Американские школьнеги совсем тупые и неграмотные, они даже ту примитивную математику не поймут.

anonymous
()

слово нечётное пишется именно так, без разрыва.
слово buffer пишется именно так, с двумя f.

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

ТС же на си пишет, так? Значит, английский знает. Надо быть совсем уж упоротым недоумком, чтобы лезть в программирование не зная английского.

anonymous
()

тред не читал

double
остаток от деления

Cool story, bro.

anonymous
()
Ответ на: комментарий от anonymous

чукча ТС не читатель, он — писатель; если у него что-то не получается, он не пойдет читать мануалы, тем более охрененную простыню из двадцати каких-то нудных теорем да еще на английском языке; он просто запостит вопрос на лоре и будет ждать, пока такой же чукча не скажет ему, как надо делать, при этом не понимая пагубность подхода «главное — работает, а разбираться что/как/почему не обязательно»

anonymous
()
Ответ на: комментарий от anonymous

ТС же на си пишет, так?

так.

Значит, английский знает.

> char bufer[200].

сомневаюсь.

nanoolinux ★★★★
()
Ответ на: комментарий от anonymous

Ну так все же, почему таки «толсто»? Надо было не открывать перед убогим ТС-ом окно в прекрасный мир просвещения, а назвать его дебилом и послать учить уроки? Так, что ли?

anonymous
()
Ответ на: комментарий от anonymous

нет, «тонко» было бы предложить заюзать long double

anonymous
()

Всем спасибо. )

Ух.. Какое обсуждение породил пост. )

Всем спасибо за хорошие ссылки по теме. Давно хотел разобраться с данной проблемой, но как-то в других языках такого не встречал, да и задач подобных небыло.. А тут спустя много лет сел за СИ и вот оно «привет из прошлого». :)

Еще раз всем спасибо!

asve79
() автор топика
Ответ на: комментарий от nanoolinux

я читал, со словарём, и даже понимал

anonymous
()
Ответ на: Всем спасибо. ) от asve79

но как-то в других языках такого не встречал

Дай-ка угадаю: «другие языки» это у тебя были всякие Mathematica, Maxima, Axiom, Common Lisp и Scheme и тому подобное говно?

Потому как во всех настоящих языках, не исключая и Питоны с Жабами, используются машинные плавучие числа.

anonymous
()
Ответ на: Всем спасибо. ) от asve79

привет из прошлого

прошлого

хм.

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

http://www.haskell.org/hoogle/?hoogle=Double

или так:

┌[~]
└> erl
Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)
1> <<1.0/float>>.
<<63,240,0,0,0,0,0,0>>
2> 
User switch command
 --> q
┌[~]

nanoolinux ★★★★
()
Ответ на: комментарий от theNamelessOne

Этот кадавр никоим образом «остатком от деления» не является, за исключением частного случая с целочисленными аргументами. По определению.

anonymous
()
Ответ на: комментарий от theNamelessOne

Приведи-ка тут определение остатка от деления. Потом попробуй найти в нем слова про округление в сторону нуля.

anonymous
()
Ответ на: комментарий от anonymous

Приведи-ка тут определение остатка от деления.

Остаток от деления x на y (y != 0) - такое число r (0 <= r < |y|), для которого найдётся такое целое q, что x = q * y + r.

Потом попробуй найти в нем слова про округление в сторону нуля.

А при чём здесь округление?

theNamelessOne ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.