точность между поплавком и двойной в C - PullRequest
0 голосов
/ 14 апреля 2019

Я понимаю, что есть несколько тем, похожих на мою, но я все еще не понимаю, поэтому я ожидаю, что кто-то может объяснить это более простым, но понятным для меня способом вместо вставки ссылок на другие темы, спасибо.

Вот пример кода:

int a = 960;
int b = 16;

float c = a*0.001;  
float d = a*0.001 + b;
double e = a*0.001 + b;

printf("%f\n%f\n%lf", c, d, e);

, который выводит:

0.960000
16.959999
16.960000

Мои два вопроса:

  1. Почему добавлениецелое число с плавающей точкой заканчивается как второй выход, но изменение числа с плавающей запятой на двойное решает проблему как третий выход?
  2. Почему третий вывод имеет такое же количество цифр, что и первый и второй выход последесятичная точка, так как это должно быть более точное значение?

Ответы [ 2 ]

1 голос
/ 14 апреля 2019

Причина, по которой они производят одинаковое количество десятичных разрядов, заключается в том, что 6 является значением по умолчанию. Вы можете изменить это, как в отредактированном примере ниже, где синтаксис %.*f. * может быть числом, показанным ниже, или во втором случае, представленным в качестве другого аргумента.

#include <stdio.h>

int main(void) {
    int a = 960;
    int b = 16;

    float c = a*0.001;  
    float d = a*0.001 + b;
    double e = a*0.001 + b;

    printf("%.9f\n", c);
    printf("%.*f\n", 9, d);
    printf("%.16f\n", e);
}

Вывод программы:

0.959999979
16.959999084
16.9600000000000009

Дополнительные десятичные разряды теперь показывают, что ни один из результатов не является точным. Одна из причин в том, что 0.001 нельзя точно закодировать как значение с плавающей запятой. Есть и другие причины, которые были подробно рассмотрены.

Один простой способ понять, почему float имеет около 2^32 различных значений, которые могут быть закодированы, однако в диапазоне float существует бесконечность действительных чисел, и только около 2^32 из них можно представить точно . В случае дроби 1/1000 в двоичном виде это повторяющееся значение (как и дробь 1/3 в десятичной дроби).

0 голосов
/ 14 апреля 2019
  1. Я думаю, что вычисление * 0,001 будет выполнено с двойной точностью в обоих случаях, тогда некоторая точность будет потеряна, если вы сохраните его как число с плавающей запятой.
  2. Вы можете выбрать, сколько десятичных цифр будет напечатано printf, написав, например, "% .10lf" (чтобы получить 10 цифр) вместо просто "% lf".
...