Да, вы можете разложить построение на операции с плавающей запятой, если эти операции ТОЧНЫ, и вы можете позволить себе единственный финал неточная операция.
К сожалению, операции с плавающей запятой скоро становятся неточными, когда вы превышаете точность мантиссы, результаты округляются. Как только появится «ошибка» округления, она будет накапливаться в дальнейших операциях...
Итак, как правило, НЕТ, вы не можете использовать такой наивный алгоритм для преобразования произвольных десятичных знаков, это может привести к неправильно округленному числу, отличающемуся от правильного на несколько ulp, как вам уже сказали другие.
НО ДАВАЙТЕ ПОСМОТРИМ, НАСКОЛЬКО МЫ МОЖЕМ ЗАЙТИ:
Если вы тщательно восстановите поплавок следующим образом:
if(biasedExponent >= 0)
return integerMantissa * (10^biasedExponent);
else
return integerMantissa / (10^(-biasedExponent));
существует риск превышения точности как при суммировании целочисленной мантиссы, если она имеет много цифр, так и при возведении 10 в степень смещенного экспонента...
К счастью, если первые две операции точны, то можно позволить себе окончательную неточную операцию * или /, благодаря свойствам IEEE результат будет округлен правильно.
Давайте применим это к числам с плавающей запятой одинарной точности, которые имеют точность 24 бита.
10^8 > 2^24 > 10^7
Отметив, что число, кратное 2, только увеличит показатель степени и оставит мантиссу неизменной, нам нужно иметь дело только со степенями 5 для возведения в степень 10:
5^11 > 2^24 > 5^10
Тем не менее, вы можете позволить себе 7-значную точность в целочисленной мантиссе и смещенный экспонент между -10 и 10.
С двойной точностью, 53 бита,
10^16 > 2^53 > 10^15
5^23 > 2^53 > 5^22
Таким образом, вы можете позволить себе 15 десятичных цифр и смещенный показатель степени между -22 и 22.
Вам решать, всегда ли ваши числа будут попадать в правильный диапазон... (Если вы действительно хитры, вы можете сбалансировать мантиссу и экспоненту, вставив/удалив конечные нули).
В противном случае вам придется использовать некоторую повышенную точность.
Если ваш язык предоставляет целые числа произвольной точности, то сделать это правильно будет немного сложно, но не так сложно, я сделал это в Smalltalk и написал об этом в блоге http://smallissimo.blogspot.fr/2011/09/уточнение-и-оптимизация.html и http://smallissimo.blogspot.fr/2011/09/reviewing-fraction-asfloat.html
Обратите внимание, что это простые и наивные реализации. К счастью, libc более оптимизирована.
person
aka.nice
schedule
28.07.2012