16

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

y = f(x)

经过一番困惑后,我们设法找出了适合我们观察到的数据点的公式:

在此处输入图像描述

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

在此处输入图像描述

除非我们绘制残差(即y = f(x) - actualY),否则我们会看到残差中出现一些线:

在此处输入图像描述

很明显,这些线是在我们的公式中应用了一些中间舍入的结果,但在哪里并不明显。最终我们意识到原来的系统(我们试图逆向工程的系统)正在将值存储在一种中间Decimal数据类型中:

  • 分数精度为8
  • 使用0.5舍入舍入模型:

我们可以通过以下方式模拟分数中的 8 位精度:

multiply by 128 (i.e. 2^8)
apply the round
divide by 128 (i.e. 2^8)

将上面的等式更改为:

在此处输入图像描述

这显着减少了残差:

在此处输入图像描述

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

  1. 表明在计算机中模拟数值表示可以帮助模型
  2. 用漂亮的图片和颜色吸引人们的注意力
  3. 在我解释为什么我要问我的问题之前,拒绝做出贡献的批评者保持沉默

现在我想在Single Precision使用浮点数的编程语言(和 Excel)中模拟浮点数Double Precision。我想这样做是因为认为这是需要的。

在上面的示例中,我认为原始系统使用的是Decimal data type with fixed 8-bit fractional precision using 0.5 round-up rules. 然后我必须找到一种方法来用Double数学模拟该计算模型。现在我认为原始系统正在使用Single精确数学,我想使用Double.

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

在我当前的模型中,我再次有属于常规线性模式的残差 - 这是四舍五入的标志:

在此处输入图像描述

问题是随着我的输入变量变得更大,错误变得更大,并且只可见。我意识到这可能是由于所有浮点数都归一化为IEEE 754 “科学记数法”这一事实引起的。

即使我错了,我仍然想尝试一下。

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

如何Single使用 模拟精确舍入Doubles


在我看来,我仍然可以应用“在 8 个小数位后舍入”的概念(尽管Single精度浮点是 24 位),只要我可以首先“规范化”该值。例如

1234567898.76543

需要转换为(类似于):

1.23456789876543 E-09

然后我可以将我的“轮到第 24 位”(即 2^24 = 16,777,216)

floor(1.23456789876543E-09 * 16777216 + 0.5) / 16777216;

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

注意:我意识到 IEEE 表示将二进制1作为最高有效位。我可能不需要复制该行为以获得正确的结果。因此,这不是交易破坏者,也不是暗示整个方法失败的理由。

也可以看看

4

4 回答 4

9

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

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

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

我不知道如何在 Excel 中执行此操作。检查手册:)(编辑添加:)我想你可以通过将数字除以2到数字的log 2的上限的幂,然后按照上面的指示进行二进制循环,得到大致相同的效果,然后反转该过程以重新创建原始指数。但我怀疑结果偶尔会遇到 Excel 关于算术的特殊想法的特殊性。

于 2012-09-23T16:31:17.430 回答
6

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

y = x + x * 0x1p29 - x * 0x1p29;

在大多数情况下,这会在 y 中产生相同的结果,就像 x 已四舍五入为浮点数(32 位二进制 IEEE 754)然后转换回双精度数(64 位)。它的工作原理是添加一个值 (x * 0x1p29),将 x 的一些位“推”出有效数字,导致第 23 位舍入,然后减去添加的值。(是 2 29 , 5368709120x1p29的十六进制浮点数。 )

在极少数情况下,它会产生略有不同的结果。如果您只是想减少模型中的噪音,这些罕见的情况可能可以忽略不计。如果你想消除它们,那么,你可以找到不大于 x 的 2 的最大幂,而不是加减 2 29 x,然后加减 2 29倍而不是 2 29 x。(要找到 2 的幂,您可以取以 2 为底的对数并取其底。但是,仍然存在可能需要补偿的舍入问题。此外,如果输入可能为零或负数,则必须避免取对数时发生的错误。)

此外,这不会重现在单精度中低于正常值或在单精度中溢出的数字的行为。

最后,在极少数情况下,计算双精度结果然后四舍五入到单精度产生的结果与最初计算单精度结果略有不同,并且没有任何四舍五入双精度结果的方法可以解决这个问题。

于 2012-09-24T17:01:39.507 回答
1

使用这样的代码(C):

double x, y;
/ ... y gets a double value somewhere ... /
x = (double)(float)y;

之后,x (double) 将具有一个由 y 舍入产生的值作为单精度浮点数。

于 2015-02-13T14:36:16.407 回答
1

您可以使用Excel VBA中的模块创建自定义函数:

Function SINGLEFLO(Eingang As Double)
    Dim MySingle As Single
    MySingle = CSng(Eingang)
    SINGLEFLO = CDbl(MySingle)
End Function

然后,您可以SINGLEFLO()在所有需要将精度限制为Single Float.

于 2020-11-09T13:44:27.630 回答