он запутан, а также иногда дает неправильный результат
В какой-то момент, учитывая базовый 2-й характер типичной с плавающей запятой, программист должен сделать выбор:
При обычном кодировании с плавающей запятой есть также выдаёт
Infinity
Not-a-number.
Странности вроде -0.0
А насколько переносимым сделать код?
Источники неточности
Использование OP int
ограничивает float
примерно до [INT_MIN ... INT_MAX]. Код не работает для float
за пределами этого диапазона. Можно использовать long long
, чтобы получить больший диапазон без значительного изменения кода. Еще лучше исследовать float modff(float value, float *iptr)
.
float f = ...;
// int a=f;
long long a=f;
Повторное использование f*=10.0
ниже с дробным значением в f
вводит возможное округление (неточность) на каждой итерации.
for(l=0;l<7;l++) {
f*=10.0;
Код не пытается округлить, учитывая, что f
не может быть 0,0 после дроби, образующей for(l=0;l<7;l++) { f*=10.0;
l oop. Я рассматриваю это как место для повышения точности. Эта область также сложна, поскольку округление может повлиять на многие ведущие цифры, когда они равны 9, что в конечном итоге потребует сдвига строкового буфера. В 0.93721
после этого l oop, f
было около 0,74. Поскольку более 0,5, округление дало бы ответ ".9371999"
-> ".9372000"
.
Код стремится к 7 десятичным цифрам после .
. Значения в виде десятичного кода, присвоенные float
соответствию от 6 до 9 значащим десятичным разрядам, включая цифры слева от .
. Ожидания не должны становиться слишком завышенными.
Идея улучшения
Если количество желаемых цифр дробной части мало, выполните 1 масштабирование / округление
// ASSUME f >= 0.0, (sign handling done before here)
long long a=f;
f-=a;
int int_f = round(f*pow(10, 7));
if (int_f < 10000000) {
later_printf_the_7_digits(int_f);
} else {
a++;
later_printf_the_7_digits(0);
}