【问题标题】:How can I justify that f64::from_bits(0x3fe9000000000000 u64 ) == 0.781250 f64我如何证明 f64::from_bits(0x3fe9000000000000 u64 ) == 0.781250 f64
【发布时间】:2020-02-16 04:50:56
【问题描述】:

我用第二个问题稍微修改了原始消息:

一位 C++ 专家建议我检查一下: https://en.cppreference.com/w/cpp/numeric/bit_cast

更好地理解doublememcpybit_cast (C++20)的表示。

在这里更具体地说,我试图理解为什么我们会从代码中得到这个结果:

    constexpr std::uint64_t u64v2 = 0x3fe9000000000000ull;
    constexpr auto f64v2 = std::bit_cast<double>(u64v2);

"f64::from_bits(0x3fe9000000000000u64) == 0.781250f64"

在此之前,我花时间研究了快速反平方根示例中提供的示例。

https://en.wikipedia.org/wiki/Fast_inverse_square_root#CITEREFGoldberg1991

我手动进行了微积分,结果我终于意识到在这种特定情况下会发生什么,指数为 8 位,尾数为 23 位。

但在我上面提到的bit_cast 的应用示例中,根据我的研究,指数似乎是 11 位,尾数是 52 位(双精度): https://en.wikipedia.org/wiki/Double-precision_floating-point_format

当我手工计算时,我发现

x = (1+Mx/L)*2^(Ex-B)

 L=2^52 and Ex = 2*(2^9- 1) with the notations of 

https://en.wikipedia.org/wiki/Fast_inverse_square_root#CITEREFGoldberg1991

我没有找到公布的 `0.781250 的结果。 也许我选择的指数和尾数不正确。 我不知道,但我真的很想了解会发生什么。

提前感谢您的解释,以帮助找到0.781250

第二个问题:请您检查我在下面提出的问题作为对评论的回复,因为即使我对第一个示例也有挑战。提前致谢

【问题讨论】:

    标签: floating-point hex double precision fixed


    【解决方案1】:

    对于3fe9000000000000,第一位(零)是符号位,所以我们可以忽略它(它是正数)。

    接下来的 11 位是 011.1111.1110 (3fe),它是 1022,但被 1023 向下调整以处理负指数。因此它是-1,它为您提供2<sup>-1</sup>0.5 的乘数。

    尾数位是1001000..0(十六进制数的9000..0)。前四位等于值0.50.250.01250.0625(每次减半)。由于只设置了第一位和第四位,因此您会得到0.5 + 0.0625 = 0.5625

    按照 IEEE754 的要求,将隐式 1 添加到该数字,您将得到一个基值 1.5625。当它乘以之前计算的乘数时,您会得到:

    1.5625 x 0.5 = 0.78125
    

    所以这就是你如何获得你的价值。


    可以在IEEE754-1985 Wikipedia page 上找到更多详细信息,您可以尝试使用Harald Schmidt's excellent online converter,这是一个非常有用的工具,我构建了自己的副本来处理双精度(不幸的是,不是在网络上,它是用于桌面的 Java 应用程序)。它真的确实帮助了我很多理解。

    您可能还想查看我在 IEEE754 上给出的 some other answers,尤其是 this one


    关于你在评论中提到的位模式,0x4172f58bc0000000(你说应该19880124,但计算别的东西),这是你如何转换它:

    4---> 1--> 7-->   2--> f--> 5--> 8--> b--> c--> (<- hex digits)
    s eee eeee eeee   mmmm mmmm mmmm mmmm mmmm mmmm
    0 100 0001 0111   0010 1111 0101 1000 1011 1100 (<- then all zeroes)
      v      v  vvv     |  ||||  | | |    | || ||            1/n
      1      1  421     |  ||||  | | |    | || |+-------- 4,194,304
      0      6          |  ||||  | | |    | || +--------- 2,097,152
      2                 |  ||||  | | |    | |+----------- 1,048,576
      4                 |  ||||  | | |    | +------------   524,288
                        |  ||||  | | |    +--------------   131,072
                        |  ||||  | | +-------------------     8,192
                        |  ||||  | +---------------------     4,096
                        |  ||||  +-----------------------     1,024
                        |  |||+--------------------------       256
                        |  ||+---------------------------       128
                        |  |+----------------------------        64
                        |  +-----------------------------        32
                        +--------------------------------         8
    

    符号为正。

    指数是1,024 + 16 + 4 + 2 + 1 = 1,047 - 1,023 bias = 24,所以乘数是2<sup>24</sup>16,777,216

    尾数位相加,每个位加上<sup>1</sup>/<sub>2<sup>n</sup></sub>n1 开始并向右增加:

    <sup>1</sup>/<sub>4,194,304</sub>, <sup>1</sup>/<sub>2,078,152</sub>, <sup>1</sup>/<sub>1,048,576</sub>, <sup>1</sup>/<sub>524,288</sub>, <sup>1</sup>/<sub>131,072</sub>, <sup>1</sup>/<sub>8,192</sub>, <sup>1</sup>/<sub>4,096</sub>, <sup>1</sup>/<sub>256</sub>, <sup>1</sup>/<sub>128</sub>, <sup>1</sup>/<sub>64</sub>, <sup>1</sup>/<sub>32</sub>,和 <sup>1</sup>/<sub>8</sub>.

    当您将所有这些与隐式 1 相加时,您将得到 1.1849477291107177734375

    那么,它和之前计算的乘数 16,777,216 的乘积就是你想要的值,19,880,124‬

    【讨论】:

    • 非常感谢您的详细解释。我现在理解得更好了。我在计算偏差指数 L 时出错。我拿了2^11 - 1,而我应该拿2^10 - 1
    • 晚上好,我继续阅读页面并进行验证。好像有误?因为这是写的(对于第一个示例): 19880124.000000f64.to_bits() == 0x4172f58bc0000000u64 我手动验证,似乎它是错误的。这将是:12f58bc0000000。您能否确认我所说的或纠正我并解释(如果我错了)?谢谢
    • @Dev,我在末尾添加了一点,展示了如何执行该特定位模式。希望对您有所帮助。
    • 我的问题是相反的:我们如何从19,880,124 获得 0x4172f58bc0000000u64 ?谢谢。是的,另一种感觉对我来说很容易,作为我发送的第一个示例
    • @Dev,如果你搜索ieee754 how to turn decimal number into bit pattern,YouTube 上有很多不错的视频。它基本上是转换为二进制分数,然后标准化为二进制科学记数法。
    【解决方案2】:

    您的号码在 IEEE-745 DP 格式中的布局如下:

                      6    5          4         3         2         1         0
                      3 21098765432 1098765432109876543210987654321098765432109876543210
                      S ----E11---- ------------------------F52-------------------------
              Binary: 0 01111111110 1001000000000000000000000000000000000000000000000000
                 Hex: 3FE9 0000 0000 0000
           Precision: DP
                Sign: Positive
            Exponent: -1 (Stored: 1022, Bias: 1023)
           Hex-float: +0x1.9p-1
               Value: +0.78125 (NORMAL)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-23
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-30
      相关资源
      最近更新 更多