如果一个浮点数在我的机器中是可表示的,那么它的倒数在我的机器中是否可以表示?

If a floating-point number is representable in my machine, will its inverse be representable in my machine?

给定一些存储正值的 double 类型的初始化对象 x,我想找到最小的 double v 例如 0 <= v < 1/x .

很明显我可以写 double v = DBL_EPSILON;,但是,如果 x 足够大,是否会发生 v 最终大于实际值 1/ x,因为它太小了,无法在我的机器中显示?

换句话说,更准确地说,如果我有一个正实数 x 和一个类型为 double 的对象 x1,其存储值恰好表示 x,是否保证表示的值by DBL_EPSILON 小于实数1/x?

如果不能保证,如何计算double类型的最大值,保证DBL_EPSILON小于实数1/x?

正无穷大的倒数当然小于任何正有理数。除此之外,由于非正规数,即使是最大的有限浮点数也具有远高于等效宽度的最小可表示浮点数的乘法逆元。

我假设 double 是 IEEE 754 binary64。

If a floating-point number is representable in my machine, will its inverse be representable in my machine?

不一定,原因有二:

  1. 倒数可能不是浮点数。

    比如3虽然是浮点数,但是1/3不是。

  2. 逆可能会溢出。

    比如2−1074的倒数就是21074,它不仅比所有的有限浮点数都大但超过最大有限浮点数 1.fffffffffffffp+1023 = 21024 − 2971 的一半是之后的下一个,21024,如果指数的范围更大。 所以 2−1074 的倒数四舍五入到无穷大。

Given some initialized object x of type double that stores a positive value, I want to find the smallest double v such as 0 <= v < 1/x.

最小的这样的总是零。 如果将其限制为非零,它将始终是最小的次正规浮点数,0x1p−1074,或大约 4.9406564584124654⟩× 10−324,而不管(除非是无穷大)。 但是也许你想要 largest 这样的而不是 smallest 这样的 .

最大的总是要么 1 ⊘ = fl(1/) (即最接近 1/ 的浮点数,这是你通过写作得到的1/x in C), 或下一个更接近于零的浮点数(可以通过在 C 中写 nextafter(1/x, 0) 得到):在默认舍入模式下,除法运算符总是 returns最接近真商的浮点数,如果有平局,则为两个最接近的浮点数之一。

您还可以通过使用 fesetround(FE_DOWNWARD)fesetround(FE_TOWARDZERO) 设置舍入模式然后仅计算 1/x 来获得最大的此类,尽管工具链对非默认舍入模式的支持参差不齐大多数情况下,它们用于消除病态代码中的错误,而不是提供可靠的舍入语义。

It seems fairly obvious that I could write double v = DBL_EPSILON;, but, if x is big enough, could it happen that v end up being bigger than the real value 1/x because it's so small that cannot be represented in my machine?

1/x 永远不会四舍五入为零,除非它是无限的或者您启用了非标准的清零语义(因此通常是次正规的结果会四舍五入为零,例如什么时候是最大的有限浮点数 0x1.fffffffffffffp+1023).

但除清零外,还有许多值 1/ 和 fl(1/) = 1/x 小于 DBL_EPSILON

例如,如果=0x1p+1000(即21000≈1.0715086071862673 × 10301),则1/= fl(1/) = 1/x = 0x1p−1000(即 2−1000 ≈ 9.332636185032189 × 10−302)是远低于 DBL_EPSILON = 0x1p−52(即 2−52 ≈ 2.220446049250313 × 10−16)。 1/ 在这种情况下是一个浮点数,因此倒数是在浮点运算中精确计算的;根本没有四舍五入。 在这种情况下,小于 1/ 的最大浮点数是 0x1.fffffffffffffp−1001,或 2−1000 − 2−1053 .

DBL_EPSILON (2−52) 不是最小的浮点数 (2−1074),或者即使是最小的正常浮点数 (2−1022)。 相反,DBL_EPSILON是从1到下一个更大的浮点数的距离,1 + 2−52,有时写成ulp(1)表示它是量级在 1.

的浮点表示中,最后一位的最低有效数字或单位

In case it is not guaranteed, how can I calculate the biggest value of type double that ensures that DBL_EPSILON is less than the real number 1/x?

那就是 1/DBL_EPSILON - 1,或者 252 − 1。 但是你要这个号码有什么用? 你为什么要在这里使用 DBL_EPSILON

If a floating-point number is representable in my machine, will its inverse be representable in my machine?

没有。没有规定 1.0/DBL_MIN <= DBL_MAX1.0/DBL_MAX <= DBL_MIN 都必须为真。一个通常是正确的。对于次法线,1.0/次法线通常 > DBL_MAX.


Given some initialized object x of type double that stores a positive value, I want to find the smallest double v such as 0 <= v < 1/x.

这是真的,因为 v 可能为零,除非对于像 DBL_MAX 这样的大 x1.0/x 为零。这是一种可能。对于次法线,这种情况很少见,因为 1.0/DBL_MAX 可以表示为大于 0 的值。

DBL_EPSILON与以上关系不大。 OP 的问题更依赖于 DBL_MAX, DBL_MIN 并且 double 支持子法线。许多关于平衡的 FP 编码,其中 1/DBL_MIN 在某种程度上是关于 DBL_MIN,但 C 不需要这种对称性。

没有。浮点数在 1.0 附近平衡以最小化计算倒数的影响,但这种平衡并不精确,指数的中间点(指数的值 0x3fff...,给出相同数量的1.0 以上和以下两个的幂。但是指数值 0x4ffff... 保留给无穷大,然后是 nans,而值 0x0000... 保留给非正规数(也称为次正规数)这些值不是归一化(有些架构甚至没有实现它们),但在那些实现的架构中,除了(但精度较低)归一化的位之外,它们还添加了与尾数宽度一样多的位作为 2 的幂,在范围 负指数。这意味着你有一组 o 数字,非常接近于零,当你计算它们的倒数时,你总是得到无穷大。

对于双打,你有 52 个 2 的幂,或者大约 15 个 10 的幂。对于 floats,这大约是 10 的 7 次方。

但这也意味着,如果您计算一个大数的倒数,您将始终得到一个不同于零的数字。