Вы лидируете на float
, который C++ определяет как IEEE 754 32-bit 'single precision' floating point type.
Если вы посмотрите формат такого значения, 32 бита разделен между тремя компонентами:
- 23 бит для хранения мантиссы
- 8 бит для хранения экспонента
- 1 бит для хранения знака.
Если у вас есть 23 бита для хранения signifcand, это означает, что наибольшее значение, которое вы можете представить в значении, равно 2^23. В результате плавающие точки с одинарной точностью имеют около 6-9 цифр точности.
Если у вас есть значение с плавающей запятой, которое имеет 9 или более цифр до десятичной точки - если оно превышает 2^23 - у вас никогда не будет дробного компонента.
Чтобы помочь этому осознаваться, рассмотрим следующий код:
void Test()
{
float test = 8388608.0F;
while(test > 0.0F)
{
test -= 0.1F;
}
}
Этот код никогда не заканчивается. Каждый раз, когда мы пытаемся уменьшить тест на 0,1, изменение величины теряется, потому что у нас нет точности его сохранения, поэтому значение заканчивается на 8388608.0. Никакой прогресс не может быть достигнут, поэтому он никогда не заканчивается. Это справедливо для всех типов с плавающей запятой с ограниченной точностью, поэтому вы обнаружите, что эта же проблема будет иметь место для типов с плавающей точкой двойной точности IEEE 754 (64-разрядная версия), все же, просто с другим большим значением.
Кроме того, если ваша цель состоит в том, чтобы сохранить как можно большую точность, тогда не имеет смысла бросать из double
в float
. double
- это 64-битный тип с плавающей точкой; float
- это 32-разрядный тип с плавающей точкой. Если вы использовали double, вы можете избежать большей части усечения, если ваши значения достаточно малы.
Вам нужно будет предоставить немного больше кода, чтобы люди могли видеть, что происходит на самом деле. Как написано, этот фрагмент кода не может компилироваться. Какую ценность вы использовали, и что записано в поток? –