Почему кастинг для int не заполняет все дубликаты в C
С учетом кода C:
#include <math.h>
#include <stdio.h>
int main(){
int i;
double f=log(2.0)/log(pow(2.0,1.0/2.0));
printf("double=%f\n",f);
printf("int=%d\n",(int) f);
}
Я получаю вывод:
double=2.000000
int=1
f, по-видимому, не менее 2,0. Почему значение отливки не равно 2?
Ответы
Ответ 1
Поскольку значение double было меньше 2
double=1.99999999999999978
int=1
Попробуйте, но на этот раз добавьте некоторую точность
#include <math.h>
#include <stdio.h>
int main(){
int i;
double f=log(2.0)/log(pow(2.0,1.0/2.0));
printf("double=%0.17f\n",f);
printf("int=%d\n",(int) f);
}
Сбивать с толку, как первый раз, когда вы это испытываете. Теперь, если вы попробуете этот
#include <math.h>
#include <stdio.h>
int main(){
int i;
double f=log(2.0)/log(pow(2.0,1.0/2.0));
printf("double=%0.17f\n",f);
printf("int=%d\n",(int) f);
printf("int=%d\n", (int)round(f));
}
Он будет правильно округлять значение. Если вы посмотрите на странице руководства (по крайней мере, на mac), вы увидите следующий комментарий...
round, lround, llround -- round to integral value, regardless of rounding direction
Что они означают по направлению, все это указано в IEEE 754. Если вы проверите различные способы округления до целого числа..., то слово указано как округление по направлению к -ve infinity
, которое в этом случае было в направлении 1
:)
Ответ 2
Целое число не принимает округленное значение, но делает усечение. Итак, если f равно 1.999999999999 [..] 9, значение int будет равно 1.
Кроме того, поскольку двойник хочет быть более точным, он возьмет округленное значение, учитывая количество символов, которое он может показать, что равно 2.000000.
Ответ 3
Типы с плавающей точкой не могут точно представлять некоторые числа. Хотя математически вычисление должно быть ровно 2 с плавающими точками IEEE754, результат оказывается немного меньше 2. Для получения дополнительной информации см. этот вопрос.
Если вы увеличиваете точность вашего вывода, указав %.20f
вместо просто %f
, вы увидите, что число не равно 2, а при печати с меньшей точностью результат просто округлен.
При преобразовании в int
, однако, используется полная точность типа с плавающей точкой, а так как оно достигает менее 2, результат при преобразовании в целое число равен 1.