【问题标题】:machine precision and max and min value of a double-precision type机器精度和双精度类型的最大值和最小值
【发布时间】:2010-02-02 16:57:31
【问题描述】:

(1) 我遇到了几个将 epsilon 添加到非负变量以保证非零值的情况。所以我想知道为什么不添加数据类型可以表示的最小值而不是 epsilon?这两者可以解决哪些不同的问题?

(2) 我还注意到双精度类型的最大值的倒数大于其最小值,其最小值的倒数是 inf,远大于其最大值。计算其最大值和最小值的倒数是否有用?

(3) 对于一个很小的正数的双精度类型,计算它的倒数,当它的倒数开始没有意义时它有多小?在倒数上设置上限更好吗?界限是多少?

感谢和问候

【问题讨论】:

    标签: c++ c


    【解决方案1】:

    厄普西隆

    Epsilon 是可与 1.0 相加并产生可与 1.0 区分开的结果的最小值。正如 Poita_ 暗示的那样,这对于处理舍入错误很有用。情况很简单:一个普通的浮点数的精度是固定的,不管数字的大小。换句话说,它总是计算相同数量的有效数字。例如,double 的典型实现将有大约 15 个有效数字(转换为 Epsilon = ~1e-15)。如果您正在使用 10e-200 范围内的数字,它可以表示的最小变化将在 10e-215 左右。如果您使用的是 10e+200 范围内的数字,它可以表示的最小变化将在 1e+185 左右。

    有效地使用 Epsilon 通常需要将其缩放到您正在使用的数字的范围内,并使用它来定义您愿意接受的范围,这可能是由于舍入错误,所以如果两个数字在该范围内范围,你假设他们可能真的是平等的。例如,对于 1e-15 的 Epsilon,您可能决定将 1e-14 范围内的数字视为相等(即,有效数字已被舍入丢失)。

    可以表示的最小数字通常会大大小于该数字。使用相同的典型double,它通常会在 1e-308 左右。这相当于 Epsilon if 您使用的是定点数而不是浮点数。例如,曾经有不少人将定点用于各种图形。一个典型的版本是一个 16 位整数,分成小数点前 10 位和小数点后 6 位。这样的数字可以表示大约从 0 到 1024 的数字,小数点后大约有两个(十进制)数字。或者,您可以将其视为有符号,从(大约)-512 到 +512,同样在小数点后保留两位数。

    在这种情况下,缩放因子是固定的,因此两个数字之间可以表示的最小差异也是固定的——即 1024 和下一个更大的数字之间的差异与 0 和下一个更大的数字。

    倒数

    我不确定您究竟为什么关心计算极大或极小数字的倒数。 IEEE 浮点使用非规范化,这意味着接近范围限制的数字会失去精度。基本上,一个数字分为指数和有效数字。指数包含数字的大小,有效数字包含有效数字。每个都用指定的位数表示。在通常情况下,数字是标准化的,这意味着它们与我们在学校都学过的科学记数法有点相似。在科学计数法中,您总是调整有效数和指数,使小数点前只有一位,因此(例如)140 变为 1.4e2,20030 变为 2.003e4,以此类推。

    将此视为浮点数的“标准化”形式。但是,假设您被限制为具有 2 位数字的指数,因此它只能从 -99 运行到 +99。还假设您最多可以有 15 个有效数字。在这些限制内,您可以生成像 0.00001002e-99 这样的数字。这使您可以表示小于 1e-99 的数字,但会损失一些精度 - 而不是 15 位精度,您使用 5 位有效数字来表示幅度,因此您只剩下 10 位数字这真的很重要。

    除了它是二进制而不是十进制之外,IEEE 浮点的工作方式大致如此。 当您接近范围的末端时,数字的精度越来越低,直到(在范围的最末端)您只剩下一点精度。

    如果你取那个只有一位精度的数字,然后取它的倒数,你会得到一个非常大的数字 - 但由于你只从一位精度开始,结果也只能有一位精度.虽然比没有结果略好,但它仍然非常接近毫无意义。您已经达到了位数可以表示的限制;解决这个问题的唯一方法是使用更多位。

    倒数(或其他计算)实际上没有任何一点“不再有意义”。在一个结果有意义而另一个没有意义的情况下,这并不是一条真正的强硬路线。相反,它是一个斜率,其中一个结果可能有 15 位精度,另一个 10 位和三分之一只有 1 位。“有意义”与否主要是您如何解释该结果。要获得有意义的结果,您需要清楚地了解最终结果中有多少位是真正有意义的。

    【讨论】:

      【解决方案2】:

      您需要了解浮点数在 CPU 中的表示方式。在数据类型中,为符号保留 1 位,即它是正数还是负数,(是的,浮点数中可以有正数和负数 0,)然后为有效数保留一些位(或尾数,)这些是浮点数中的有效数字,最后为指数保留了一些位。现在浮点数的值是:

      -1^sign * 有效数 * 2^exponent

      1. 这意味着最小的数字是一个非常小的值,即具有最低指数的最小有效数。然而,舍入误差要大得多,并且取决于数字的大小,即具有给定指数的最小数字。 epsilon 是 1.0 与下一个可表示的较大值之间的差值。这就是为什么在对舍入误差具有鲁棒性的代码中使用 epsilon 的原因,如果你做得对,你应该用你使用的数字的大小来缩放 epsilon。最小的可表示值通常没有任何意义。

      2. 您会看到标准化最小值和非标准化最小值之间的差异。问题是,由于使用有效数的方式,可以使负指数大于正指数,例如有效数的位模式除最后一位外全为零,即为一,则指数有效降低有效位数中的位数。对于最大值,您无法做到这一点,即使您将有效数字设置为全1,有效指数仍然只是给定的指数。即考虑 0.000001e-10 和 9.999999e+10 之间的差异,第一个比第二个大得多。第一个实际上是 1e-16,而第二个大约是 1e+11。

      3. 当然取决于浮点数的精度。在双精度的情况下,最大值和下一个较小值之间的差异已经很大(沿着 10^292 的线),所以你的舍入误差会很大。如您所见,如果值太小,您只会得到 inf 。真的,没有严格的答案,这完全取决于您需要的数字的精度。鉴于舍入误差约为 epsilon*magnitude,如果您需要将数字精确到 1e-3,则 (1/epsilon) 的倒数已经具有大约 1.0 的舍入误差,那么即使 epsilon 也太大而无法除以。

      有关背景信息,请参阅IEEE754 和 Machine epsilon 上的这些维基百科页面。

      【讨论】:

        【解决方案3】:
        1. 添加 Epsilon 是为了测试两个应该相等的值之间的相等性,但不是因为舍入错误。虽然您可以对 epsilon 使用最小的正值,但它不是最优的,因为它太小了。浮点运算导致的舍入误差几乎总是超过最小值,因此需要更大的 epsilon。多大取决于您想要的精度。

        2. 我不明白这个问题。倒数有什么用?我想不出它们有用的任何理由。

        3. 通常,除以非常小的值是一个坏主意,因为它会导致非常大的舍入误差。我不确定添加上限是什么意思。尽可能避免除以小值。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 2023-04-09
        • 2017-09-07
        • 1970-01-01
        • 2013-03-04
        相关资源
        最近更新 更多