可以存储在IEEE 754双类型中而不损失精度的最大“无浮动”整数是多少?

换句话说,at会返回以下代码片段:

UInt64 i = 0;
Double d = 0;

while (i == d)
{
        i += 1; 
        d += 1;
}
Console.WriteLine("Largest Integer: {0}", i-1);

当前回答

正如其他人所指出的,我将假设OP要求最大的浮点值,以便所有小于其本身的整数都可以精确表示。

你可以使用float.h中定义的FLT_MANT_DIG和DBL_MANT_DIG来不依赖于显式值(例如,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

其他回答

1.7976931348623157 × 10^308

http://en.wikipedia.org/wiki/Double_precision_floating-point_format

在IEEE 754 double(64位)中可以表示的最大整数与该类型可以表示的最大值相同,因为该值本身就是一个整数。

这表示为0x7FEFFFFFFFFFFFFF,它由:

符号位0(正)而不是1(负) 最大指数0x7FE(2046表示减去偏差后的1023)而不是0x7FF(2047表示NaN或无穷大)。 最大尾数0xFFFFFFFFFFFFF是52位全1。

在二进制中,值是隐式的1,后面是尾数中的另外52个1,然后是指数中的971个0(1023 - 52 = 971)。

精确的十进制值为:

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464 234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559 332123348274797826204144723168738177180919299881250404026184124858368

这大约是1.8 x 10308。

维基百科在同样的背景下引用了IEEE 754的链接:

在典型的计算机系统中,“双精度”(64位)二进制浮点数的系数为53位(其中一个是隐含的),指数为11位,以及一个符号位。

2^53略大于9 * 10^15。

更新1:

刚刚意识到5 ^ 1074不是你可以从IEEE 754双精度浮点中免费得到的真正上限,因为我只计算了非规整指数,忘记了尾数本身可以适合另外22次5的事实,所以据我所知,一个人可以从双精度格式中免费得到的5的最大次幂是:

5的最大次方:

5 ^ 1096

最大奇数:

5 ^ 1074 x 9007199254740991 5 ^ 1074 x (2 ^ 53 - 1)

开始 CONVFMT =“IEEE754: 4字节word: %.16lX”; print”“, sprintf(%。”* g ", __=(_+=_+=_^=_<_)^++_+_*(_+_), {1ch88ff88} {1ch88ff88} {1ch88ff88} {1ch88ff88} {1ch88ff88} {1ch88ff88} {1ch88ff88} {1ch88ff88} {1ch88ff88} ' 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双精度中实际上“最大”的整数,没有任何大int库或外部函数调用,具有完全完整的尾数,是可计算、可存储和可打印的:

9,007,199,254,740,991 * 5 ^ 1074(~2546.750773909…比特)

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

我使用xxhash将其与gnu-bc进行比较,并确认它确实是相同的,没有精度损失。这个数字没有任何“非规格化”的地方,尽管指数范围被这样标记。

如果你不相信,在你自己的系统上试试。(我通过现成的mawk得到了这个打印)-你也可以很容易地得到它:

一(1)次幂/幂(^ aka **) op, 一个(1)乘(*)运算, 一次(1)sprintf()调用,和 任一(一)项 - substr()或regex-gsub() 执行必要的清理

就像我们经常提到的1.79…E309数字,

都是尾数有限公司 两者都是指数受限的 两者都有大得离谱的ulp(最后一名) 两者都距离浮点单元的溢出或下溢只有一步之遥,可以返回一个可用的答案

对工作流的二进制指数进行否定,您可以完全在这个空间中完成操作,然后在工作流的尾部再次反转它,以回到我们通常认为的“较大”的一侧,

但要记住,这是倒置的 指数领域,不存在“逐渐溢出”

- 4Chan出纳员

的确,对于64位的IEEE754双精度,所有到9007199254740992 == 2^53的整数都可以精确表示。

然而,值得一提的是,所有超出4503599627370496 == 2^52的可表示数字都是整数。 超过2^52,测试它们是否是整数就没有意义了,因为它们都隐式舍入到附近一个可表示的值。

在2^51到2^52的范围内,唯一的非整数值是以“”结尾的中点。5”,这意味着计算后的任何整数测试都必须产生至少50%的错误答案。

在2^51以下也有"25"和"。75英寸,所以比较一个数字和它的四舍五入的对应数字,以确定它是否可能是整数开始是有意义的。

TLDR:如果您想测试计算结果是否可能是整数,请避免大于2251799813685248 == 2^51的数字