Точность вывода выше, чем двойная точность

Я печатаю некоторые данные из программы C++ для обработки/визуализации с помощью ParaView, но у меня проблема с числами с плавающей запятой. Paraview поддерживает типы данных Float32 и Float64. Float64 эквивалентен double с типичными ограничениями +/-1,7e +/- 308. Но мой код печатает числа вроде 6,5e-318. Это вызывает ошибки в ParaView при чтении данных. Я убедился, что округление этих маленьких чисел до нуля приводит к исчезновению ошибок в ParaView. Я не уверен, почему у меня такой «высокоточный» вывод, возможно, потому, что некоторые числа хранятся с более высокой точностью, чем двойная. Например, следующий код воспроизводит такое же поведение в моей системе:

#include <iostream>
int main(void)
{
  const double var1 = 1.0e-318, var2 = 1.5e-318;
  std::cout << 1.0e-318 << std::endl; 
  std::cout << var1 << std::endl; 
  std::cout << var1 - var2 << std::endl; 
  std::cout.setf(std::ios_base::fixed | std::ios_base::scientific, std::ios_base::floatfield);
  std::cout << 1.0e-318 << std::endl; 
  std::cout << var1 << std::endl; 
  std::cout << var1 - var2 << std::endl; 

  return 0;
}

Мой вывод:

9.99999e-319
9.99999e-319
-4.99999e-319
9.99999e-319
9.99999e-319
-4.99999e-319

Моя система представляет собой Mac OS X Snow Leopard, и я протестировал вышеуказанное с GCC 4.2 и GCC 4.6 с флагами -m32, -m64 и -ffloat-store (не уверен, что это полезно).

На самом деле вывод для меня в порядке, а для ParaView нет. Я просто хочу знать, почему у меня такая разница. Скорее всего, я игнорирую что-то, связанное с числами с плавающей запятой, что может быть важно. Не могли бы вы дать мне некоторое представление об этом выводе/числовом поведении для удвоения?


person iluvatar    schedule 30.09.2011    source источник
comment
В чем именно здесь проблема? Я не вижу никакой разницы между до и после. 1.0e-318 на самом деле IS 9.99999e-319   -  person GreenScape    schedule 30.09.2011
comment
@GreenScape: Проблема, похоже, в том, что обычные двойные числа опускаются только до ~ 2,2e-308, а все остальные результаты представляют собой денормализованные числа с плавающей запятой, снижаясь до ~ 4,9e-324. Многие программы не понимают денормализованные числа с плавающей запятой.   -  person PlasmaHH    schedule 30.09.2011


Ответы (1)


Субнормальные числа, то есть числа с наименьшим возможным показателем степени и ведущими нулями в дроби, могут быть меньше 1E. -308, до 1E-324. Вероятно, вы можете отфильтровать их, используя std::numeric_limits.

person thiton    schedule 30.09.2011
comment
Да, я думаю, что это может быть решением, если сравнить фактический двойной минимум и текущее число. Спасибо за указание на информацию о субнормальных числах. - person iluvatar; 30.09.2011