Наибольшее целое число, которое может быть сохранено в двойном

Какое наибольшее целое число без плавающих может быть сохранено в двойном типе IEEE 754 без потери точности?

12 ответов

Решение

Наибольшее / наибольшее целое число, которое может храниться в двойном значении без потери точности, совпадает с наибольшим возможным значением двойного числа. То есть, DBL_MAX или примерно 1,8 × 10 308 (если ваш двойник является 64-битным двойником IEEE 754). Это целое число. Это представлено точно. Что вы еще хотите?

Продолжайте, спросите меня, какое наибольшее целое число такое, чтобы оно и все меньшие целые числа могли быть сохранены в 64-битных двойных числах IEEE без потери точности. IEEE 64-битный дубль имеет 52 бита мантиссы, поэтому я думаю, что это 2 53:

  • 2 53 + 1 не может быть сохранено, потому что 1 в начале и 1 в конце имеют слишком много нулей между ними.
  • Все, что меньше 2 53, может быть сохранено, с 52 битами, которые явно хранятся в мантиссе, а затем экспонента дает вам еще один.
  • 2 53, очевидно, могут быть сохранены, так как это небольшая степень 2.

Или другой способ взглянуть на это: как только смещение было снято с показателя степени, и игнорируя знаковый бит как не относящийся к вопросу, значение, хранимое в double, является степенью 2 плюс 52-битное целое число, умноженное на 2 показатель степени - 52. Таким образом, с показателем 52 вы можете сохранить все значения от 2 52 до 2 53 - 1. Затем с показателем 53 следующее число, которое вы можете сохранить после 2 53, равно 2 53 + 1 × 2 53 - 52. Таким образом, потеря точности сначала происходит с 2 53 + 1.

9007199254740992 (это 9 007 199 254 740 992) без каких-либо гарантий:)

программа

#include <math.h>
#include <stdio.h>

int main(void) {
  double dbl = 0; /* I started with 9007199254000000, a little less than 2^53 */
  while (dbl + 1 != dbl) dbl++;
  printf("%.0f\n", dbl - 1);
  printf("%.0f\n", dbl);
  printf("%.0f\n", dbl + 1);
  return 0;
}

Результат

9007199254740991
9007199254740992
9007199254740992

Наибольшее целое число, которое может быть представлено в двойном (64-разрядном) IEEE 754, совпадает с наибольшим значением, которое может представлять тип, поскольку само это целое число.

Это представляется как 0x7FEFFFFFFFFFFFFF, который состоит из:

  • Знаковый бит 0 (положительный), а не 1 (отрицательный)
  • Максимальный показатель 0x7FE (2046, который представляет 1023 после смещения вычитается), а не 0x7FF (2047, который указывает на NaN или бесконечность).
  • Максимальная мантисса 0xFFFFFFFFFFFFF что составляет 52 бита все 1.

В двоичном виде значение представляет собой неявную 1, за которой следуют еще 52 единицы из мантиссы, затем 971 ноль (1023 - 52 = 971) от показателя степени.

Точное десятичное значение:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368

Это примерно 1,8 х 10308.

Википедия говорит об этом в том же контексте со ссылкой на IEEE 754:

В типичной компьютерной системе двоичное число с плавающей запятой с двойной точностью (64-разрядное) имеет коэффициент 53 бита (один из которых подразумевается), показатель степени 11 бит и один знаковый бит.

2 ^ 53 составляет чуть более 9 * 10^15.

Вам нужно посмотреть на размер мантиссы. 64-разрядное число IEEE 754 с плавающей запятой (которое имеет 52 бита плюс 1 подразумевается) может точно представлять целые числа с абсолютным значением, меньшим или равным 2^53.

Это правда, что для 64-битного IEEE754 double все целые числа до 9007199254740992 == 2^53 могут быть точно представлены.

Однако стоит также отметить, что все представимые числа за пределами 4503599627370496 == 2^ 52 являются целыми числами. За пределами 2 ^ 52 становится бессмысленным проверять, являются ли они целыми числами, потому что все они неявно округляются до ближайшего представимого значения.

В диапазоне от 2 ^51 до 2 ^ 52 единственными нецелыми значениями являются средние точки, оканчивающиеся на ".5", что означает, что любой целочисленный тест после вычисления должен дать как минимум 50% ложных ответов.

Ниже 2 ^51 у нас также есть «0,25» и «.75», поэтому сравнение числа с его округленным эквивалентом, чтобы определить, может ли оно быть целым или нет, начинает иметь некоторый смысл.

TL; DR: если вы хотите проверить, может ли вычисленный результат быть целым числом, избегайте чисел больше 2251799813685248 == 2 ^51

DECIMAL_DIG от <float.h> должен дать хотя бы разумное приближение к этому. Так как это имеет дело с десятичными цифрами, и оно действительно хранится в двоичном формате, вы, вероятно, можете хранить что-то немного большее, не теряя точности, но сколько именно трудно сказать. Я полагаю, вы должны быть в состоянии понять это из FLT_RADIX а также DBL_MANT_DIG, но я не уверен, что полностью доверю результату.

Двойники, «простое» объяснение

Наибольшее «двойное» число (число двойной точности с плавающей запятой) обычно представляет собой 64-битное или 8-байтовое число, выражаемое как:

      1.79E308
or
1.79 x 10 (to the power of) 308

Как вы можете догадаться, 10 в степени 308 — это ГИГАНТСКОЕ ЧИСЛО, например 17000000000000000000000000000000000000000000000 и даже больше!

На другом конце шкалы 64-битные числа с плавающей запятой двойной точности поддерживают крошечные крошечные десятичные числа дробей с использованием «точечной» нотации, наименьшее из которых:

      4.94E-324
or
4.94 x 10 (to the power of) -324

Все, что умножается на 10 в отрицательной степени, представляет собой крохотное десятичное число, например 0,00000000000000000000000000000000000494 и даже меньше.

Но что смущает людей, так это то, что они слышат, как компьютерщики и математики говорят: «но это число имеет диапазон только из 15 значений чисел». Получается, что описанные выше значения — это МАКСИМАЛЬНЫЕ и МИНИМАЛЬНЫЕ значения за все время, которые компьютер может хранить и представлять из памяти. Но они теряют точность и способность создавать числа НАДОЛГО ДО того, как станут такими большими. Таким образом, большинство программистов ИЗБЕГАЮТ максимально возможного двойного числа и пытаются придерживаться известного, гораздо меньшего диапазона.

Но почему? И какое максимальное двойное число лучше всего использовать? Я не мог найти ответ, читая десятки плохих объяснений на математических сайтах в Интернете. Так что это ПРОСТОЕ объяснение может помочь вам ниже. Мне помогло!!

ДВОЙНОЕ ЧИСЛО ФАКТОВ и НЕДОСТАТКОВ

JavaScript (который также использует 64-битную систему хранения чисел с двойной точностью в компьютерах) использует числа с плавающей запятой двойной точности для хранения всех известных числовых значений. Таким образом, он использует те же МАКС. и МИН. диапазоны, что и выше. Но большинство языков используют типизированную систему счисления с диапазонами, чтобы избежать проблем с точностью. Однако системы хранения двойных и плавающих чисел, по-видимому, имеют один и тот же недостаток, заключающийся в потере числовой точности по мере того, как они становятся больше и меньше. Я объясню почему, так как это влияет на идею «максимальных» значений...

Чтобы решить эту проблему, в JavaScript есть так называемое значение Number.MAX_SAFE_INTEGER , которое равно . Это наиболее точное число, которое оно может представлять для целых чисел, но НЕ самое большое число, которое можно сохранить. Он точен, потому что гарантирует, что любое число, равное или меньшее, может быть просмотрено, вычислено, сохранено и т. д. За пределами этого диапазона есть «отсутствующие» числа. Причина в том, что числа с двойной точностью ПОСЛЕ используют дополнительное число, чтобы умножить их на все большие и большие значения, включая истинное максимальное число . Это новое число называется показателем степени.

ЗЛОЙ ВЫРАЗИТЕЛЬ

Дело в том, что это максимальное значение также является максимальным числом, которое вы можете хранить в 53 битах компьютерной памяти, используемой в 64-битной системе хранения. Это число, хранящееся в 53-битной области памяти, представляет собой максимально возможное значение, которое может быть сохранено непосредственно в мантиссе памяти типичного числа двойной точности с плавающей запятой, используемого в JavaScript.

, между прочим, находится в формате, который мы называем Base10 или десятичным числом, используемым людьми. Но оно также хранится в памяти компьютера как 53-битное, как это значение...

      11111111111111111111111111111111111111111111111111111

Это максимальное количество битов, которое компьютеры могут фактически хранить целой частью чисел с двойной точностью, используя 64-битную систему памяти чисел.

Чтобы получить даже БОЛЬШОЕ максимально возможное число (), JavaScript должен использовать дополнительный трюк, называемый показателем степени , чтобы умножить его на все большие и большие значения. Итак, естьномер рядом сзначение в памяти компьютера выше, что позволяет числу расти намного больше и намного меньше, создавая окончательный диапазон чисел, которые, как ожидается, будут представлены двойным значением. (Кроме того, есть один бит для положительных и отрицательных чисел.)

После того, как компьютер достигает этого предела максимального целочисленного значения (около ~9 квадриллионов) и заполняет секцию мантиссы памяти 53 битами, JavaScript использует новую 11-битную область хранения для экспоненты , которая позволяет увеличивать гораздо большие целые числа (до 10 в степени 308!) и гораздо меньшие десятичные числа, чтобы получить меньше (10 в степени -324!). Таким образом, этот показатель степени позволяет создавать полный диапазон больших и малых десятичных знаков с плавающей системой счисления или десятичной точкой для перемещения вверх и вниз по числу, создавая сложные дробные или десятичные значения, которые вы ожидаете увидеть. Опять же, эта экспонента является еще одним хранилищем больших чисел в 11 битах и ​​сама имеет максимальное значение .

Вы заметите, что это максимальное целое число, но не объясняет большее МАКСИМАЛЬНОЕ значение, возможное в хранилище, или МИНИМАЛЬНОЕ десятичное число, или даже то, как создаются и сохраняются десятичные дроби. Как это компьютерное битовое значение создает все это?

Ответ снова через экспоненту!

Оказывается, 11-битное значение экспоненты делится на положительное и отрицательное значение, так что оно может создавать большие целые числа, но также и маленькие десятичные числа.

Для этого у него есть свой положительный и отрицательный диапазон, созданный вычитаниемот егомаксимальное значение, чтобы получить новый диапазон значений изк(минус зарезервированные значения для 0), чтобы создать диапазон положительных/отрицательных показателей. Чтобы затем получить ОКОНЧАТЕЛЬНОЕ ДВОЙНОЕ ЧИСЛО, мантисса () умножается на показатель степени (плюс добавленный однобитовый знак), чтобы получить окончательное значение! Это позволяет экспоненте умножать значение мантиссы на еще большие целые диапазоны за пределами 9 квадриллионов, но также и наоборот с десятичной дробью до очень маленьких дробей.

Однако число -+1023, хранящееся в экспоненте , не умножается на мантиссу для получения двойного числа, а используется для повышения числа.в степень экспоненты. Показатель степени представляет собой десятичное число, но не применяется к десятичному показателю степени, такому как 10 в степени или 1023. Он снова применяется к системе Base2 и создает значение.

Это сгенерированное значение затем умножается на мантиссу , чтобы получить число MAX и MIN, разрешенное для хранения в JavaScript, а также все большие и меньшие значения в пределах диапазона. Он использует «2», а не 10 для целей точности, поэтому с каждым увеличением значения экспоненты он только удваивает значение мантиссы. Это снижает потери номеров. Но этот экспоненциальный множитель также означает, что он будет терять увеличивающийся диапазон чисел в удвоениях по мере его роста, до точки, где, когда вы достигаете МАКСИМАЛЬНОГО хранимого экспоненты и возможной мантиссы, очень большие ряды чисел исчезают из окончательного вычисленного числа, и, таким образом, определенные числа теперь невозможны в математических вычислениях!

Вот почему большинство использует БЕЗОПАСНЫЕ максимальные целочисленные диапазоны (или меньше), поскольку большинство знает, что очень большие и маленькие числа в JavaScript очень неточны! Также обратите внимание, что 2 в степени -1023 дает число MIN или небольшие десятичные дроби, которые вы связываете с типичным «плавающим числом». Таким образом, экспонента используется для преобразования целого числа мантиссы в очень большие и малые числа вплоть до Максимального и Минимального диапазонов, которые он может хранить.

Обратите внимание, чтопереводится в десятичный показатель с использованиемдля максимальных значений. Это позволяет вам видеть число в человеческих значениях или числовом формате Base10 двоичного вычисления. Часто специалисты по математике не объясняют, что все эти значения являются одним и тем же числом просто в разных основаниях или форматах.

ИСТИННЫЙ МАКСИМАЛЬНЫЙ МАКСИМАЛЬНЫЙ МАКСИМАЛЬНЫЙ БЕСКОНЕЧНОСТЬ

Наконец, что происходит, когда целые числа достигают МАКСИМАЛЬНОГО возможного числа или наименьшей возможной десятичной дроби?

Оказывается, числа с плавающей запятой двойной точности зарезервировали набор битовых значений для 64-битных значений экспоненты и мантиссы для хранения четырех других возможных чисел:

  1. +Бесконечность
  2. -Бесконечность
  3. +0
  4. -0

Например, +0 в двойных числах, хранящихся в 64-битной памяти, представляет собой большую строку пустых битов в памяти компьютера. Ниже показано, что происходит после того, как вы выходите за пределы наименьшего возможного десятичного числа () при использовании числа с плавающей запятой двойной точности. Это становится после того, как у него заканчивается память! Компьютер вернет , но сохранит в памяти 0 бит. Ниже приведен ПОЛНЫЙ 64-битный дизайн хранилища в битах для двойника в памяти компьютера. Первый бит управляет(0) или(1) для положительных или отрицательных чисел следующим является 11-битный показатель степени (все нули равны 0, поэтому становится) и большой блок из 53 битов для мантиссы или мантиссы , который представляет 0. Таким образом,представлен всеми нулями!

      0 00000000000 0000000000000000000000000000000000000000000000000000

Если двойное число достигает своего положительного максимума или минимума или отрицательного максимума или минимума, многие языки всегда будут возвращать одно из этих значений в той или иной форме. Однако некоторые возвращают NaN или переполнение, исключения и т. д. Как это обрабатывается, это отдельная тема. Но часто эти четыре значения являются вашими ИСТИННЫМИ минимальными и максимальными значениями для double. Возвращая иррациональные значения, вы, по крайней мере, имеете представление max и min в двойных числах, которые объясняют последние формы двойного типа, которые не могут быть сохранены или объяснены рационально.

КРАТКОЕ СОДЕРЖАНИЕ

Таким образом, МАКСИМАЛЬНЫЙ и МИНИМАЛЬНЫЙ диапазоны для положительных и отрицательных удвоений следующие:

      MAXIMUM TO MINIMUM POSITIVE VALUE RANGE
1.79E308 to 4.94E-324 (+Infinity to +0 for out of range)

MAXIMUM TO MINIMUM NEGATIVE VALUE RANGE
-4.94E-324 to -1.79E308 (-0 to -Infinity for out of range)

But the SAFE and ACCURATE MAX and MIN range is really:
9007199254740991 (max) to -9007199254740991 (min)

Таким образом, вы можете видеть, что с добавлением +-Infinity и +-0 у двойников есть дополнительные максимальные и минимальные диапазоны, которые помогут вам, когда вы превысите максимальные и минимальные значения.

Как упоминалось выше, когда вы переходите от наибольшего положительного значения к наименьшему десятичному положительному значению или дроби, биты обнуляются, и вы получаете 0 Past.двойное значение не может хранить меньшее значение десятичной дроби, поэтому оно сворачивается до +0 в битовом реестре. То же самое происходит с крошечными отрицательными десятичными знаками, значение которых уменьшается до -0. Как вы знаете, -0 = +0, поэтому, хотя в памяти хранятся разные значения, в приложениях они часто принудительно обнуляются. Но имейте в виду, что многие приложения доставляют нули со знаком!

Противоположное происходит с большими значениями... в прошломони превращаются в + Бесконечность и - Бесконечность для отрицательной версии. Это то, что создает все странные диапазоны чисел в таких языках, как JavaScript. Числа с двойной точностью имеют странные результаты!

Обратите внимание, что МИНИМАЛЬНЫЙ БЕЗОПАСНЫЙ ДИАПАЗОН для десятичных знаков/дробей не показан выше, поскольку он зависит от точности, необходимой для дроби. Когда вы комбинируете целое число с дробной частью, точность десятичного разряда быстро снижается по мере уменьшения. Об этом в сети много дискуссий и дискуссий. Ни у кого никогда нет ответа. Список ниже может помочь. Возможно, вам придется изменить эти диапазоны, перечисленные на гораздо меньшие значения, если вы хотите гарантировать точность. Как видите, если вы хотите поддерживать точность до 9 знаков после запятой в числах с плавающей запятой, вам нужно будет ограничить МАКСИМАЛЬНЫЕ значения в мантиссе этими значениями. Точность означает, сколько знаков после запятой вам нужно с точностью. Небезопасно означает, что после этих значений число потеряет точность и будет иметь пропущенные числа:

                  Precision   Unsafe 
            1           5,629,499,534,21,312
            2           703,687,441,770,664
            3           87,960,930,220,208
            4           5,497,558,130,888
            5           68,719,476,736
            6           8,589,934,592
            7           536,870,912
            8           67,108,864
            9           8,388,608

Мне потребовалось некоторое время, чтобы понять ИСТИННЫЕ пределы чисел с плавающей запятой двойной точности и компьютеров. Я создал это простое объяснение, приведенное выше, после того, как прочитал в Интернете так много МАССОВОЙ ЗАБЛУЖДЕННОСТИ от математических экспертов, которые отлично умеют вычислять числа, но ужасно умеют что-либо объяснять! Надеюсь, я помог вам в вашем путешествии по программированию - Мир :)

ОБНОВЛЕНИЕ 1 :

только что понял5 ^ 1074НЕ является истинным верхним пределом того, что вы можете получить бесплатно из IEEE 754 с плавающей запятой двойной точности, потому что я считал только денормализованные показатели степени и забыл тот факт, что сама мантисса может соответствовать еще 22 степеням 5, так что в меру своих возможностей Понимая, что наибольшая степень числа 5, которую можно получить бесплатно из формата двойной точности, равна ::

наибольшая степень числа 5:

  • 5 ^ 1096

наибольшее нечетное число:

  • 5 ^ 1074 х 9007199254740991

  • 5 ^ 1074 х ( 2 ^ 53 - 1 )

       mawk 'BEGIN { OFS = "\f\r\t";

 CONVFMT = "IEEE754 :: 4-byte word :: %.16lX"; 
   
 print "", 
 sprintf("%.*g", __=(_+=_+=_^=_<_)^++_+_*(_+_),
                ___=_=((_+_)/_)^-__),   (_ ""),
                        \
 sprintf("%.*g",__,_=_*((_+=(_^=!_)+(_+=_))*_\
                           )^(_+=_++)), (_ ""),
                           \
 sprintf("%.*g",__,_=___*=  \
        (_+=_+=_^=_<_)^--_^_/--_-+--_), (_ "") }'
  • 4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625e-324

              — IEEE754 :: 4-byte word :: 0000000000000001
    
    494065645841246544176568792......682506419718265533447265625 } 751 dgts :      
      5^1,074    
    
  • 1.1779442926436580280698985883431944188238616052015418158187524855152976686244219586021896275559329804892458073984282439492384355315111632261247033977765604928166883306272301781841416768261169960586755720044541328685833215865788678015827760393916926318959465387821953663477851727634395732669139543975751084522891987808004020022041120326339133484493650064495265010111570347355174765803347028811562651566216206901711944564705815590623254860079132843479610128658074120767908637153514231969910697784644086106916351461663273587631725676246505444808791274797874748064938487833137213363849587926231550453981511635715193075144590522172925785791614297511667878003519179715722536405560955202126362715257889359212587458533154881546706053453699158950485070818103849887847900390625e-308

              — IEEE754 :: 4-byte word :: 000878678326EAC9
    
    117794429264365802806989858......070818103849887847900390625 } 767 dgts :
      5^1,096
    
  • 4.4501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375e-308

              — IEEE754 :: 4-byte word :: 001FFFFFFFFFFFFF
    
    445014771701440227211481959......317493580281734466552734375 } 767 dgts :
          5^1,074
          6361
          69431
          20394401 
    

и вот быстроawkфрагмент кода, чтобы распечатать каждую положительную степень от 2 до 1023 , каждую положительную степень от 5 до 1096 и их общую степень нуля, оптимизированную как для с, так и безbigintбиблиотека:

      {m,g,n}awk' BEGIN {

 CONVFMT = "%." ((_+=_+=_^=_<_)*_+--_*_++)(!++_) "g"
    OFMT = "%." (_*_) "g"

 if (((_+=_+_)^_%(_+_))==(_)) {
    print __=_=\
            int((___=_+=_+=_*=++_)^!_)
     OFS = ORS
    while (--___) {
        print int(__+=__), int(_+=_+(_+=_))
    }
    __=((_+=_+=_^=!(__=_))^--_+_*_) substr("",_=__)
    do {
        print _+=_+(_+=_) } while (--__)
    exit
 } else { _=_<_ }

    __=((___=_+=_+=++_)^++_+_*(_+_--))
      _=_^(-(_^_--))*--_^(_++^_^--_-__)
  _____=-log(_<_)
    __^=_<_
   ___=-___+--___^___

 while (--___) {
     print ____(_*(__+=__+(__+=__))) }
 do {
     print ____(_) } while ((_+=_)<_____)
 }

 function ____(__,_) {
     return (_^=_<_)<=+__ \
     ?              sprintf( "%.f", __) \
     : substr("", _=sprintf("%.*g", (_+=++_)^_*(_+_),__),
         gsub("^[+-]*[0][.][0]*|[.]|[Ee][+-]?[[:digit:]]+$","",_))_
 }'

==============================

зависит от того, насколько вы гибки с определением "представленный" и "представимый" -

Несмотря на то, что говорится в типичной литературе, целое число, которое на самом деле является «самым большим» вIEEE 754 double precision, без какой-либо библиотеки bigint или внешнего вызова функции, с полностью полной мантиссой , которая вычисляется, сохраняется и печатается, на самом деле:

9,007,199,254,740,991 * 5 ^ 1074 (~2546.750773909... bits)

        4450147717014402272114819593418263951869639092703291
  2960468522194496444440421538910330590478162701758282
  9831782607924221374017287738918929105531441481564124
  3486759976282126534658507104573762744298025962244902
  9037796981144446145705102663115100318287949527959668
  2360399864792509657803421416370138126133331198987655
  1545144031526125381326665295130600018491776632866075
  5595837392240989947807556594098101021612198814605258
  7425791790000716759993441450860872056815779154359230
  1891033496486942061405218289243144579760516365090360
  6514140377217442262561590244668525767372446430075513
  3324500796506867194913776884780053099639677097589658
  4413789443379662199396731693628045708486661320679701
  7728916080020698679408551343728867675409720757232455
  434770912461317493580281734466552734375

я использовалxxhashсравнить это сgnu-bcи подтвердил, что он действительно идентичен и точность не потеряна. В этом числе вообще нет ничего «денормализованного», несмотря на то, что диапазон показателей помечен как таковой.

Попробуйте на своей системе, если не верите мне. (Я получил эту распечатку через готовуюmawk) - и вы также можете легко добраться до него:

  1. один(1) возведение в степень/мощность (^он же**) оп,
  2. одно(1) умножение (*) оп,
  3. один (1)sprintf()звонок, и
  4. либо один (1) из -substr()или регулярное выражение-gsub()произвести необходимую очистку

Как и часто упоминаемый номер 1.79…E309,

  • оба имеют ограничение по мантиссе
  • оба имеют экспоненциальное ограничение
  • у обоих смехотворно большиеULPs (unit in last place)
  • и оба находятся ровно в 1 шаге от «переполнения» блока с плавающей запятой либо переполнением, либо недостаточным переполнением, чтобы дать вам полезный ответ

Отмените двоичные показатели рабочего процесса, и вы можете полностью выполнять операции в этом пространстве, а затем просто инвертировать его еще раз в конце рабочего процесса, чтобы вернуться к той стороне, которую мы обычно считаем «большей».

       but keep in mind that in the inverted 
exponent realm, there's no "gradual overflow"

— Кассир 4Chan

Как отмечали другие, я предполагаю, что OP запросил наибольшее значение с плавающей запятой, чтобы все целые числа, меньшие, чем он сам, были точно представлены.

Ты можешь использовать FLT_MANT_DIG а также DBL_MANT_DIG определено в float.h не полагаться на явные значения (например, 53):

      #include <stdio.h>
#include <float.h>

int main(void)
{
    printf("%d, %.1f\n", FLT_MANT_DIG, (float)(1L << FLT_MANT_DIG));
    printf("%d, %.1lf\n", DBL_MANT_DIG, (double)(1L << DBL_MANT_DIG));
}

выходы:

      24, 16777216.0
53, 9007199254740992.0

Рассмотрим ваш компилятор, который может не соответствовать текущей спецификации IEEE 754 Double Type. Вот исправленный фрагмент, который можно попробовать в VB6 или Excel VBA. Он выходит из цикла по адресу 999 999 999 999 999, что составляет всего 1/9 ожидаемого значения. При этом не проверяются все числа, поэтому может быть меньшее число, приращение которого на 1 не увеличивает сумму. Вы также можете попробовать следующую строку в окне отладки: Print Format(1E15# + 1#,"#,###")

          Microsoft VB6, Microsoft Excel 2013 VBA (Both obsolete) 
    Sub TestDbl()
    Dim dSum    As Double      'Double Precision Sum
    Dim vSum    As Variant     'Decimal Precision Sum
    Dim vSumL   As Variant     'Last valid comparison
   
    Dim dStep   As Double
    Dim vStep   As Variant
   
    dStep = 2# ^ 49#           'Starting step
    vStep = CDec(dStep)
   
    dSum = dStep               'Starting Sums
    vSum = vStep
    vSumL = vSum
   
   
    Debug.Print Format(dSum, "###,###,###,###,###,###,###"); " "; _
                Format(vSum, "###,###,###,###,###,###,###"); " "; _
                vStep; " "; Now()
    Do
       dSum = dSum + dStep     'Increment Sums
       vSum = CDec(vSum + vStep)
                              
       If dSum <> vSum Then
                              'Print bad steps
          Debug.Print Format(dSum, "###,###,###,###,###,###,###"); " "; _
                      Format(vSum, "###,###,###,###,###,###,###"); " "; _ 
                      vStep; " "; Now()
                              'Go back 2 steps
          vSum = CDec(vSumL - vStep)
          dSum = CDbl(vSum)
                              'Exit if Step is 1
          If dStep < 2 Then Exit Do
                              'Adjust Step, if <1 make 1
          vStep = CDec(Int(vStep / 4))
          If vStep < 2 Then vStep = CDec(1)
          dStep = CDbl(vStep)
       End If                  'End check for matching sums
       vSumL = vSum            'Last Valid reading
       DoEvents
    Loop                       'Take another step
                               'Last Valid step
    Debug.Print Format(dSum, "###,###,###,###,###,###,###"); " "; _
                Format(vSum, "###,###,###,###,###,###,###"); " ";  _
                vStep; " "; Now()
   
    End Sub
Другие вопросы по тегам