Floating point 如何用双精度模拟单精度舍入?

Floating point 如何用双精度模拟单精度舍入?,floating-point,double,floating-accuracy,ieee-754,Floating Point,Double,Floating Accuracy,Ieee 754,我遇到了一个问题,我试图重建现有系统中使用的公式,一个相当简单的一个输入和一个输出公式: y = f(x) 经过一番费解,我们终于找到了符合观测数据点的公式: 正如你所看到的,我们的理论模型非常适合观测数据: 除了绘制残差(即,y=f(x)-实际上)时,我们看到残差中出现了一些行: 很明显,这些线是在我们的公式中应用一些中间舍入的结果,但在哪里不明显。最终,人们意识到原始系统(我们正在尝试反向工程的系统)正在以中间数据类型存储值: 分数的8位精度 使用0.5四舍五入四舍五入模型: 我

我遇到了一个问题,我试图重建现有系统中使用的公式,一个相当简单的一个输入和一个输出公式:

y = f(x)
经过一番费解,我们终于找到了符合观测数据点的公式:

正如你所看到的,我们的理论模型非常适合观测数据:

除了绘制残差(即,y=f(x)-实际上)时,我们看到残差中出现了一些行:

很明显,这些线是在我们的公式中应用一些中间舍入的结果,但在哪里不明显。最终,人们意识到原始系统(我们正在尝试反向工程的系统)正在以中间数据类型存储值:

  • 分数的8位精度
  • 使用0.5四舍五入四舍五入模型:
我们可以通过以下方式模拟分数中的8位精度:

multiply by 128 (i.e. 2^8)
apply the round
divide by 128 (i.e. 2^8)
将上述等式改为:

这大大减少了残余误差:

以上所有内容与我的问题无关,除了:

  • 表明在计算机上模拟数值表示有助于模型的建立
  • 用漂亮的图片和色彩吸引人们的注意力
  • 让批评我的人保持沉默,直到我知道为什么我要问我的问题

  • 现在我想在使用双精度浮点数的编程语言(和Excel)中模拟单精度浮点数。我想这样做是因为我认为这是我所需要的

    在上面的示例中,我认为原始系统使用的是
    十进制数据类型,具有固定的8位小数精度,使用0.5取整规则
    。然后我必须找到一种方法,用
    Double
    math模拟计算模型。现在我认为原来的系统使用的是
    单精度
    数学,我想用
    双精度
    来模拟

    如何使用双精度模拟单精度舍入

    在我当前的模型中,我再次发现残差属于规则的线性模式——这是舍入的一个信号:

    问题是,当我的输入变量变大时,错误变得更大,并且只可见。我意识到这可能是因为所有浮点数都被规范化为“科学符号”

    即使我错了,我还是想试试

    即使我不想尝试,我仍然在问这个问题

    如何使用
    双精度
    模拟
    单精度
    舍入


    在我看来,我仍然可以应用“8个小数位后舍入”的概念(尽管24位表示单精度浮点),只要我可以首先“规范化”值。e、 g

    1234567898.76543
    
    需要转换为(类似于):

    然后,我可以将我的“舍入”应用到第24位(即2^24=16777216)

    那么,问题是我可以应用
    符号
    abs
    ln
    exp
    (或其他函数)的什么组合,以便“规范化”我的值,将其四舍五入到第n个二进制位,然后“反规范化”它

    注意:我意识到IEEE表示将二进制
    1
    保留为最高有效位。为了得到正确的结果,我可能不需要重复这种行为。因此,它不是一个交易破坏者,也没有理由认为整个方法是失败的

    另见

    您希望使用库函数frexp和ldexp,它们是标准的C99函数,在Lua中可用

    frexp接受一个浮点数,并将尾数与指数分开。结果尾数为0或在[0.5,1.0]或(-1.0,0.5)范围内。然后,您可以以明显的方式删除任何额外的位(
    floor(例如,对于非负值,尾数*2^k)/2^k)。(编辑为添加:)在调用ldexp时,最好从指数中减去k,而不是像图所示进行除法,因为我非常确定Lua不能保证2^k是精确的

    ldexp是frexp的倒数;您可以使用它将截断的数字重新组合在一起


    我不知道如何在Excel中执行此操作。请查看手册:)(编辑为添加:)我想您可以获得大致相同的效果,方法是将数字除以2,再除以该数字的对数2上限的幂,然后按上面所示进行二进制四舍五入,然后颠倒过程重新创建原始指数。但我怀疑,Excel关于算术的独特想法偶尔会导致结果的特殊性。

    您可以使用以下方法获得单精度舍入的大部分效果:

    y = x + x * 0x1p29 - x * 0x1p29;
    
    在大多数情况下,这会在y中产生相同的结果,就像x被四舍五入为浮点(32位二进制IEEE 754),然后转换回double(64位)。它通过添加一个值(x*0x1p29)来工作,该值将x的一些位“推”出有效位,导致位23处的舍入,然后减去所添加的值。(
    0x1p29
    是229536870912的十六进制浮点。)

    在极少数情况下,它会产生稍微不同的结果。如果您只想减少模型中的噪声,这些罕见的情况可能可以忽略不计。如果你想消去它们,那么,你可以找到2的最大幂不大于x,而不是加和减229x,然后加和减229倍,而不是229x。(要求2的幂,可以取以2为底的对数并取其底。但是,仍然存在舍入问题,可能需要进行补偿。此外,如果输入mig
    floor(1.23456789876543E-09 * 16777216 + 0.5) / 16777216;
    
    y = x + x * 0x1p29 - x * 0x1p29;
    
    double x, y;
    / ... y gets a double value somewhere ... /
    x = (double)(float)y;
    
    Function SINGLEFLO(Eingang As Double)
        Dim MySingle As Single
        MySingle = CSng(Eingang)
        SINGLEFLO = CDbl(MySingle)
    End Function