Учитывая следующий фрагмент кода, я просто хочу знать
Я изучил файлы float.h на своем компьютере, но не могу найти точное определение этих макроконстант.
Тестовый код (платформа = Win7-64bit)
#include <cfloat>
#include <iomanip>
cout<<"FLT_MAX ="<< setprecision(40) << FLT_MAX << endl;
cout<<"DBL_MAX ="<< setprecision(40) << DBL_MAX << endl;
cout<<"LDBL_MAX ="<< setprecision(40) << LDBL_MAX << endl;
cout<<"FLT_MIN ="<< setprecision(40) << FLT_MIN << endl;
cout<<"DBL_MIN ="<< setprecision(40) << DBL_MIN << endl;
cout<<"LDBL_MIN ="<< setprecision(40) << LDBL_MIN << endl;
32-битный результат (MinGW-20120426)
FLT_MAX =340282346638528859811704183484516925440
DBL_MAX =1.797693134862315708145274237317043567981e+308
LDBL_MAX =1.189731495357231765021263853030970205169e+4932
FLT_MIN =1.175494350822287507968736537222245677819e-038
DBL_MIN =2.225073858507201383090232717332404064219e-308
LDBL_MIN =3.362103143112093506262677817321752602598e-4932
64-битный результат (MinGW64-TDM 4.6)
FLT_MAX =340282346638528860000000000000000000000
DBL_MAX =1.7976931348623157e+308
LDBL_MAX =1.132619801677474e-317
FLT_MIN =1.1754943508222875e-038
DBL_MIN =2.2250738585072014e-308
LDBL_MIN =1.132619801677474e-317
Благодарю.
[Редактировать]: Используя последнюю версию MinGW64-TGM 4.7.1, «ошибки» LDBL_MAX, LDBL_MIN, похоже, удалены.LDBL_MAX =1.132619801677474e-317
звучит как ошибка где-то. Стандарт требует, чтобы каждое значение, представимое как double
также может быть представлен в виде long double
так что это не допустимо для LDBL_MAX < DBL_MAX
, Учитывая, что вы не показали свой реальный код тестирования, я лично проверил бы это, прежде чем обвинять компилятор.
Если действительно есть (не ошибка) разница в long double
между этими двумя значениями основание этой разницы будет заключаться в том, что ваш 32-разрядный компилятор использует более старые операции x87 с плавающей запятой, которые имеют точность 80 бит и, следовательно, допускают 80 бит long double
,
Ваш 64-битный компилятор использует более новые 64-битные операции с плавающей запятой в x64. Нет 80-битной точности, и это не мешает переключиться на инструкции x87 для реализации большего long double
,
Там, вероятно, больше сложностей, чем это. Например, не все x86-компиляторы обязательно имеют 80-битный long double
, То, как они примут это решение, зависит от разных вещей, в том числе от того, что SSE2 имеет 64-битные операции с плавающей запятой. Но возможности таковы, что long double
такой же размер как double
или что оно больше.
почему 64-битная версия не может расширять столько цифр, сколько в 32-битной версии
заполнить «40» точность вывода?
Двойной имеет только около 15 десятичных цифр точности. Цифры за пределами этого иногда информативны, но обычно вводят в заблуждение.
Я не могу вспомнить, что говорит стандарт setprecision
, но при условии, что реализация позволяет нарисовать линию, где она перестает генерировать цифры, точность double
это разумное место для рисования. Что касается того, почему одна реализация решила сделать это, а другая нет — я не знаю. Поскольку это разные дистрибутивы, они могут использовать совершенно разные стандартные библиотеки.
Та же «ложная точность» — вот почему вы видите 340282346638528859811704183484516925440
для FLT_MAX в одном случае, но 340282346638528860000000000000000000000
в другом. Один компилятор (точнее, одна реализация библиотеки) потратил много времени на то, чтобы вычислить много цифр. Другой сдался рано и округлено.
Чтобы ответить на этот вопрос, я сделаю только несколько предположений:
1) что вы проверяли это только на 64-битной машине
2) что компиляторы — это разные битовые версии одной и той же подверсии (то есть они практически родственные компиляторы).
Это было сказано:
Из «ИСО / МЭК 14882 МЕЖДУНАРОДНЫЙ СТАНДАРТ Первое издание 1998-09-01»
3.9.1 Основные типы
- Существует три типа с плавающей точкой: float, double и long double. Тип double обеспечивает, по крайней мере, такую же точность, как и float, а тип long double обеспечивает, по крайней мере, такую же точность, что и double. Набор значений типа float является подмножеством набора значений типа double; набор значений типа double является подмножеством набора значений типа long double. Представление значений типов с плавающей запятой определяется реализацией. Интегральные и плавающие типы вместе называются арифметическими типами. Специализации стандартного шаблона numeric_limits (18.2) должны определять максимальное и минимальное значения каждого арифметического типа для реализации.
Кроме того, разные процессоры будут иметь разное влияние на конечный результат, насколько точность с более высокими числами уровня. То же самое касается компиляторов. Компилятор VC ++ не будет вести себя так же, как borland, GCC / G ++ и так далее.