0

В одном из моих приложений я пытаюсь поставить значение с плавающей запятой в строке поток, как это:Потеря точности в stringstream

stream << static_cast<float>(double value); 

Вместо того, чтобы все значения с плавающей точкой я получаю только целую часть этого. Любая идея, почему это может случиться?

+0

Вам нужно будет предоставить немного больше кода, чтобы люди могли видеть, что происходит на самом деле. Как написано, этот фрагмент кода не может компилироваться. Какую ценность вы использовали, и что записано в поток? –

ответ

-1

Вы лидируете на 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, вы можете избежать большей части усечения, если ваши значения достаточно малы.

+0

Стандарт C++ ** не устанавливает ** float' как тип IEEE 754. Это довольно часто, но это не требуется. –

+0

Этот ответ не затрагивает вопрос. –

+0

Я попробовал кастинг в двойной, он все еще не работает – Bakyr