По их словам, double и long double идентичны по размеру и диапазону (см. скриншот ниже). Это противоречит этим спецификациям:
Здесь нет противоречия. Если вы внимательно прочитали стандарт и статью по ссылке, вы увидите, что стандарт C определяет минимально возможные диапазоны типов, а не какие-то фиксированные размеры для них. Также обратите внимание, что приведенная выше вики-ссылка предназначена для C, а не для C++. Это очень разные языки. К счастью, они оба согласны с размерами типов.
Это обеспечивает гибкость, поскольку C и C++ всегда разрабатывались с учетом переносимости. Основная философия заключается в том, что "вы не платите за то, что не используете", поэтому реализации компилятора должны выбирать то, что лучше и эффективнее для каждой конкретной архитектуры. Они не могут заставить int
быть всегда 32-битной. Например, в 18-битной архитектуре int будет иметь 18-битный размер вместо неудобного 32-битного размера, а 16-битным процессорам не придется тратить циклы на поддержку 32-битного int, если int
определен как 16-битный тип.
Вот почему C и C++ допускают дополнение до 1 и величину знака для целочисленных типов со знаком, а не только дополнение до 2. Типы с плавающей запятой также не обязаны иметь фиксированный размер или быть двоичными, поэтому реализации могут использовать десятичные типы с плавающей запятой. На самом деле IEEE-754 даже не требуется, потому что были компьютеры, использующие другие форматы с плавающей запятой. См. раздел Есть ли какие-либо реальные процессоры, не использующие IEEE 754?
Итак, читаем стандарт ISO/IEC 9899:201x C++, раздел 5.2.4.2.1 (Размеры целочисленных типов <limits.h>
), мы знаем, что:
Приведенные ниже значения должны быть заменены постоянными выражениями, подходящими для использования в #if
директивах предварительной обработки. […] Их значения, определенные реализацией, должны быть равны или больше по величине (абсолютное значение) показанным, с тем же знаком
Значение, соответствующее INT_MAX
, равно 32767, что означает, что INT_MAX >= 32767
во всех соответствующих реализациях. То же самое относится к типам с плавающей запятой в разделе 5.2.4.2.2 (Характеристики типов с плавающей запятой <float.h>
)
То, что вы читаете в стандарте, означает
- точностьOf(плавающая) ⩽ точностьOf(двойная) ⩽ точностьOf(длинная двойная) и
- setOfValues(float) ⊂ setOfValues(double) ⊂ setOfValues(long double)
Все очень четко и совсем не туманно. На самом деле вам гарантировано только
- СИМВОЛ_БИТ ⩾ 8
- sizeof(char) ⩽ sizeof(short) ⩽ sizeof(int) ⩽ sizeof(long) ⩽ sizeof(long long)
- sizeof(float) ⩽ sizeof(double) ⩽ sizeof(long double)
- FLT_DECIMAL_DIG ⩾ 6
- LDBL_DECIMAL_DIG ⩾ DBL_DECIMAL_DIG ⩾ 10
Таким образом, double
может иметь тот же размер и точность, что и long double
. На самом деле они обычно имеют один и тот же тип на платформах, отличных от x86, потому что у них нет тип с расширенной точностью, например x86. В последнее время многие реализации перешли на программный формат IEEE-754 четырехкратной точности. для long double
, но, конечно, это будет намного медленнее
Поскольку существует множество возможных форматов для long double
, существуют также различные варианты выбора размера long double
, например, когда людям не нужна дополнительная точность или не нужна низкая производительность программной реализации. Например
- GCC для x86 имеет
-mlong-double-64/80/128
в зависимости от того, хотите ли вы 64-разрядную (т. е. то же, что и double
), 80-битный (увеличенная точность) или 128-битный (четверная точность) long double
. Точно так же есть варианты -m96/128bit-long-double
, если вы хотите обменять скорость на 25% использования памяти.
- GCC для PowerPC имеет
-mabi=ibmlongdouble/ieeelongdouble
для реализация двойной двойной точности или стандартный формат четверной точности который имеет более широкий диапазон и немного лучшую точность, но намного медленнее
C++ существует уже давно. Почему до сих пор нет единого стандарта для такого рода вещей? Намеренно ли это ради гибкости -- каждый решает сам, какими будут эти типы данных
Именно так, как я сказал выше, это намеренно ради гибкости. Вы не платите за потерю производительности и использования памяти, когда вам не нужна точность выше double
. Комитет по стандартизации заботится обо всех возможных архитектурах, в том числе о некоторых, возможно, мертвых1.
На самом деле разрешение более высоких long double
иногда приводит к неожиданным результатам, когда FLT_EVAL_METHOD = 2, потому что операции float
и double
также выполняются с более высокой точностью, поэтому одно и то же выражение в разных точках может давать разные результаты. Кроме того, невозможно векторизовать нечетную расширенную точность long double
math2, что еще больше снижает производительность. Поэтому даже в x86 MS компилятор cl.exe полностью отключает использование 80-битных длинных двойных
Смотрите также
1 См.
2 См.
person
phuclv
schedule
11.09.2019
at least
: en.cppreference.com/w/cpp/language /types Что касаетсяlong double
- очень старые версии VS (16-битные) использовали x87 80-битный тип float для long double, но с введением SSE он устарел. gcc сохранил 80-битный тип, VS пошел с long double == double. - person Dan M.   schedule 03.05.2018long double
на этой конкретной платформе? Утверждения типа long double имеют тот же размер, что и double, или больше (до ... байтов), являются расплывчатыми и предназначены только для стандарта. - person phuclv   schedule 12.09.2019