Ian*_*oyd 16 floating-point double floating-accuracy ieee-754
我有一个问题,我试图重建现有系统中使用的公式,一个输入和一个输出的相当简单的公式:
y = f(x)
Run Code Online (Sandbox Code Playgroud)
在经历了很多令人费解之后,我们设法找出了符合我们观察数据点的公式:
正如您所看到的,我们的理论模型非常适合观察数据:
除了我们绘制残差(即y = f(x) - actualY
)时,我们看到残差中出现了一些线:
很明显,这些线是在我们的公式中应用一些中间舍入的结果,但是在哪里不明显.最终意识到原始系统(我们正在尝试逆向工程的系统)将值存储在中间Decimal
数据类型中:
我们可以通过以下方式模拟分数中的这个8位精度:
multiply by 128 (i.e. 2^8)
apply the round
divide by 128 (i.e. 2^8)
Run Code Online (Sandbox Code Playgroud)
将上面的等式改为:
这显着减少了残留误差:
现在,上述所有内容与我的问题无关,除了:
现在我想在Single Precision
使用Double Precision
浮点数的编程语言(和Excel)中模拟浮点数.我想这样做是因为我认为这是需要的.
在上面的例子中,我认为原始系统使用的是Decimal data type with fixed 8-bit fractional precision using 0.5 round-up rules
.然后,我必须找到一种用Double
数学模拟该计算模型的方法.现在我认为原始系统正在使用Single
精确数学,我想模拟使用Double
.
如何使用双精度模拟单精度舍入?
在我当前的模型中,我再次将残差归入常规线性模式 - 这是四舍五入的标志:
问题是,当输入变量变大时,错误变得更大,并且只能看到.我意识到这很可能是因为所有浮点数都被归一化为IEEE 754 "科学记数法".
即使我错了,我还是想尝试一下.
即使我不想尝试,我仍然会问这个问题
我如何
Single
使用Doubles
?来模拟精确舍入?
在我看来,我仍然可以应用"在8个小数位后舍入"的概念(尽管24位用于Single
精度浮点),只要我可以首先"标准化"该值.例如
1234567898.76543
Run Code Online (Sandbox Code Playgroud)
需要转换成(类似于):
1.23456789876543 E-09
Run Code Online (Sandbox Code Playgroud)
然后我可以将我的"轮到第24位"(即2 ^ 24 = 16,777,216)
floor(1.23456789876543E-09 * 16777216 + 0.5) / 16777216;
Run Code Online (Sandbox Code Playgroud)
这个问题,那么,是什么样的组合sign
,abs
,ln
,exp
(或其他功能),可我可能适用,这样我可以"正常化"我的价值,其舍入为n个二进制位,然后是"非标准化"吗?
注意:我意识到IEEE表示将二进制保持1
为最重要的位.我可能不需要复制该行为以获得正确的结果.因此,它不是一个交易破坏者,也不是因为它表明整个方法都是失败的.
您想使用库函数frexp和ldexp,它们是标准的C99函数,并且可以在Lua中使用.
frexp采用浮点数并将尾数与指数分开.得到的尾数是0或在[0.5,1.0)或(-1.0,0.5)范围之一.然后你可以以明显的方式删除任何额外的位(floor(mantissa * 2^k)/2^k
例如,对于非负值).(编辑为添加:)最好从ldexp调用中的指数中减去k而不是如图所示进行除法,因为我很确定Lua不能保证2 ^ k是精确的.
ldexp是frexp的反函数; 您可以使用它将截断的数字重新组合在一起.
我不知道如何在Excel中执行此操作.检查手册:)(编辑添加:)我想你可以通过将数字除以数字的log 2的上限的幂来获得大致相同的效果,然后如上所示进行二进制舍入,然后反转过程以重新创建原始指数.但我怀疑结果偶尔会出现Excel对算术的奇特想法的特殊性.
您可以使用以下方法获得舍入到单精度的大部分效果:
y = x + x * 0x1p29 - x * 0x1p29;
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,这会在y中产生相同的结果,就好像x已经四舍五入为浮点数(32位二进制IEEE 754),然后转换回双精度(64位).它通过添加一个值(x*0x1p29)来"推"出有效数字中的某些x,导致第23位舍入,然后减去添加的值.(0x1p29
是十六进制浮点2 29,536870912.)
在极少数情况下,它会产生略微不同的结果.如果您只想降低模型中的噪音,这些极少数情况可能会微不足道.如果你想消灭他们,然后,而不是加减2 29 X,你能找到的2的最大功率不大于x和加减2 29倍,而不是2 29 X.(为了找到2的幂,你可以取两个对数并取其底线.但是,仍然存在可能需要补偿的舍入问题.此外,如果输入可能为零或负数,则必须避免取其对数时出现的错误.)
此外,这不会重现单精度次正规或以单精度溢出的数字的行为.
最后,在极少数情况下,计算双精度结果然后舍入到单精度会产生与最初计算单精度结果略有不同的结果,并且没有舍入双精度结果的方法将解决此问题.
归档时间: |
|
查看次数: |
3782 次 |
最近记录: |