Как я могу обосновать, что f64 :: from_bits (0x3fe9000000000000 u64) == 0.781250 f64 - PullRequest
2 голосов
/ 19 октября 2019

Я немного изменил исходное сообщение со вторым вопросом:

Мне посоветовал эксперт по C ++: https://en.cppreference.com/w/cpp/numeric/bit_cast

, чтобы лучше понять представление double, memcpy и bit_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

2-й вопрос : пожалуйста, вы можете проверить вопрос, который я задал ниже, как ответ на комментарий, потому что даже у меня есть проблема с первым примером. заранее спасибо

Ответы [ 2 ]

4 голосов
/ 19 октября 2019

При 3fe9000000000000 первый бит (ноль) является знаковым битом, поэтому мы можем игнорировать его (это положительно).

Следующие 11 битов 011.1111.1110 (3fe), чторавно 1022, но оно уменьшается на 1023 для обработки отрицательных показателей. Поэтому -1, что дает вам множитель 2<sup>-1</sup> или 0.5.

Биты мантиссы равны 1001000..0 (9000..0 вашего шестнадцатеричного числа). Эти первые четыре бита соответствуют значениям 0.5, 0.25, 0.0125 и 0.0625 (каждый раз делятся пополам). Поскольку установлены только первый и четвертый биты, вы получаете 0.5 + 0.0625 = 0.5625.

. При добавлении неявного 1 к этому номеру, как предписано IEEE754, вы получаете базовое значение 1.5625. Когда это умножается на множитель, вычисленный ранее, вы получаете:

1.5625 x 0.5 = 0.78125

То есть это как вы получаете свое значение.


Более подробную информацию можно найти нана странице IEEE754-1985 в Википедии , и вы можете поэкспериментировать с превосходным онлайн-конвертером Харальда Шмидта , чертовски полезным инструментом, я также создал свою собственную копию для обработки двойной точности (нев Интернете, к сожалению, это было Java-приложение для рабочего стола). Это действительно действительно мне очень помогло в понимании.

Возможно, вы также захотите взглянуть на некоторые другие ответы , которые я дал на IEEE754, включая этот в частности.


Относительно битового шаблона, который вы привели в комментарии, 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>, когда n начинается с 1 и увеличивается вправо:

<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‬.

1 голос
/ 20 октября 2019

Вот как выглядит ваш номер в формате 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...