joh*_*ose 0 .net c# floating-point precision
我最近一直在研究.NET中的浮点双精度问题.在阅读Jon Skeet的文章Binary浮点和.NET时,我有一个问题.
让我们从46.428292315077文章中的例子开始.
表示为64位双精度,这相当于以下位:
Sign Exponent Mantissa
0 10000000100 0111001101101101001001001000010101110011000100100011
Run Code Online (Sandbox Code Playgroud)
一位用于表示符号,11位用于表示指数,52位用于表示尾数.注意双精度1023的偏差(我假设是允许负指数 - 后面会有更多内容).
我的困惑在于代表指数的11位,以及它们对大数的使用(或缺乏),特别是double.MaxValue(1.7976931348623157E+308).
对于指数,文章中引用了一些特殊值来帮助确定数字的值.全零表示0; 所有的代表NaN和正/负无穷大.有11位可以使用:指数的第一位是偏差,所以我们可以忽略它.这给了我们10位控制指数的实际大小.
指数on double.MaxValue为308,可用9位(100110100或带偏差:)表示10100110100.最小的小数值是double.Epsilon(4.94065645841247E-324),其指数仍然可以用9位(101000100或带偏差:)表示00101000100.
您可能会注意到偏差后的第一位似乎总是浪费掉.我对负指数的假设是否正确?如果是这样,为什么偏差浪费后的第二位呢?无论如何,它似乎是我们可以表示的实际最大数字(同时尊重特殊值和偏差后的可能符号位)111111111(或511在基数10中).
如果偏差后的位实际上被浪费了,为什么我们不能用大于324的指数表示数字呢?我对此有何误解?
Eri*_*ert 13
双重中没有浪费的比特.
让我们理解你的困惑.我们如何将比特的双重转化为数学值?让我们假设双重不是零,无穷大,负无穷大,NaN或非正规,因为这些都有特殊的规则.
你混淆的关键是将十进制数量与二进制数量混合在一起.对于这个答案,我将把所有二进制数量this formatting和十进制数量放在常规格式中.
我们采取的尾数的52位,我们把他们之后 1. 所以在你的榜样,这将是
1.0111001101101101001001001000010101110011000100100011
Run Code Online (Sandbox Code Playgroud)
那是二进制数.所以1 + 0/2 + 1/4 + 1/8 + 1/16 + 0/32 ......
然后我们取指数的11位,将其视为11位无符号整数,并从该值中减去1023.所以在你的例子中我们10000000100有无符号整数1028.减去1023,得到5.
现在我们将"小数位"(哈哈)移动5个位置:
101110.01101101101001001001000010101110011000100100011
Run Code Online (Sandbox Code Playgroud)
请注意,这相当于乘以2 5. 它不会乘以10 5!
现在,如果符号位是0,则将整个事物乘以1,如果符号位是,则将-1 乘以1.所以最后的答案是
101110.01101101101001001001000010101110011000100100011
Run Code Online (Sandbox Code Playgroud)
让我们看一个带负指数的例子.
假设指数已经存在01111111100.那是1020作为无符号整数.减去1023.我们得到-3,所以我们将向左移动三个位置,并获得:
0.0010111001101101101001001001000010101110011000100100011
Run Code Online (Sandbox Code Playgroud)
让我们看一个带有大指数的例子.如果指数已经11111111100怎么办?
解决它.那是十进制的2044.减去1023.那是1021.所以这个数字将是乘以1.01110011011011010010010010000101011100110001001000112 1021时得到的极大数字.
所以那个double的值恰好等于
32603055608669827528875188998863283395233949199438288081243712122350844851941321466156747022359800582932574058697506453751658312301708309704448596122037141141297743099124156580613023692715652869864010740666615694378079258090383719888417882332809291228958035810952632190230935024250237637887765563383983636480
大约是3.26030556 x 10 307.
那现在清楚了吗?
如果这个主题让你感兴趣,这里有一些进一步的阅读:
将double解码为其部分的代码:
https://ericlippert.com/2015/11/30/the-dedoublifier-part-one/
一个简单的任意精度理性:
https://ericlippert.com/2015/12/03/the-dedoublifier-part-two/
将双重转化为完全合理的代码:
https://ericlippert.com/2015/12/07/the-dedoublifier-part-three/
浮标表示:
https://blogs.msdn.microsoft.com/ericlippert/2005/01/10/floating-point-arithmetic-part-one/
Benford定律如何用于最小化表示错误:
https://blogs.msdn.microsoft.com/ericlippert/2005/01/13/floating-point-and-benfords-law-part-two/
我们使用什么算法将浮点数显示为十进制数?
当您尝试比较不同精度级别的相等浮点数时会发生什么?
标准算术的哪些属性无法保持浮点状态?
无限和分裂如何代表零?
https://blogs.msdn.microsoft.com/ericlippert/2009/10/15/as-timeless-as-infinity/
| 归档时间: |
|
| 查看次数: |
622 次 |
| 最近记录: |