Моя главная цель - написать функцию, которая преобразует:
- (десятичное) числовое значение с нормализованной двойной точностью в памяти
- нормализованная двойная точность в памяти до (десятичного) числового значения
т. Е.
from10toNdp(86.125) # 0100000001010101100010000000000000000000000000000000000000000000 (sign|exponent|significand)
fromNdpTo10(0100000001010101100010000000000000000000000000000000000000000000) # 86.125
На пути к созданию from10toNdp
и fromNdpTo10
я проделал следующее.
Я написал несколько помощников:
from10to2 <- function(decimalnumber) {
binaryvector <- rep(0, 1 + floor(log(decimalnumber, 2)))
while (decimalnumber >= 2) {
power <- floor(log(decimalnumber, 2))
binaryvector[1 + power] <- 1
decimalnumber <- decimalnumber - 2^power }
binaryvector[1] <- decimalnumber %% 2
paste(rev(binaryvector), collapse = "")}
from10to2(8) # "1000"
Функция from10to2
отлично работает для целых чисел, меньших 2 ^ 53 = 9.007199e15 (т. Е. Она работает и для целых чисел, хранящихся также как double; работает для значений, превышающих 2147483647); для чисел больше 2 ^ 53 он начинает терять цифры.
ПРИМЕР 1: Преобразовать 0,3-64-разрядное нормализованное число двойной точности:
Знак: 0: позитивный; 1: отрицательный
sprintf("%a", 0.3) # ("0x1.3333333333333p-2")16
library(BMS)
BMS::hex2bin("3333333333333") # (0011001100110011001100110011001100110011001100110011)2=significand=(3333333333333)16
Так как последние три «p-2» и «BiasedExponent = RealExponent + 1023bias» выходных данных sprintf
(смещение: 2 ^ (11-1) -1 = 1023), показатель степени (11 бит) равен -2 + 1023 = 1021
from10to2(1021) # ("01111111101")2
Двойная точность хранения:
0 | 01111111101 | 0011001100110011001100110011001100110011001100110011
знак | показатель | мантисса
ПРИМЕР2: Преобразовать -2,94 в 64-разрядное нормализованное число с двойной точностью:
Знак: 0: позитивный; 1: отрицательный
sprintf("%a", -2.94) # "-0x1.7851eb851eb85p+1"
library(BMS)
BMS::hex2bin("7851eb851eb85") # (0111100001010001111010111000010100011110101110000101)2=significand=(7851eb851eb85)16
Так как последние три «p + 1» и «BiasedExponent = RealExponent + 1023bias» выходных данных sprintf
(смещение: 2 ^ (11-1) -1 = 1023), показатель степени (11 бит) равен 1 + 1023 = 1024.
from10to2(1024) # ("10000000000")2
Двойная точность хранения:
1 | 10000000000 | 0111100001010001111010111000010100011110101110000101
знак | показатель | мантисса
ПРИМЕР3: Преобразовать 86.125 в 64-разрядное нормализованное число с двойной точностью:
Знак: 0: позитивный; 1: отрицательный
sprintf("%a", 86.125) # "0x1.588p+6"
library(BMS)
BMS::hex2bin("588") # (010110001000)2=significand=(588)16
Так как последние три «p + 6» и «BiasedExponent = RealExponent + 1023bias» выходных данных sprintf
(смещение: 2 ^ (11-1) -1 = 1023), показатель степени (11 бит) равен 6 + 1023 = 1029.
from10to2(1029) # ("10000000101")2
Двойная точность хранения:
0 | 10000000101 | 010110001000 (но это не 64-битный, а 1 + 11 + 12 = 24-битный!)
знак | показатель | мантисса.
Истинная 64-битная двойная точность должна быть:
0 | 10000000101 | 0101100010000000000000000000000000000000000000000000.
Таким образом, этот метод не может найти последние 40 нулей, но может правильно найти первые 24 бита.
Онлайн конвертеры:
- https://www.exploringbinary.com/floating-point-converter/
"Raw Binary (поле знака | поле экспоненты | поле значимости и поле) Double:"
- http://www.binaryconvert.com/convert_double.html
Моя методика (которая работает для 0,3 и -2,94) неожиданно перестает работать для 86,125 и не выдает 64-разрядную версию.
Почему техника останавливается на 86,125?
Уже есть способ конвертировать:
- (десятичное) числовое значение с нормализованной двойной точностью в памяти
- нормализованная двойная точность в памяти до (десятичного) числового значения?
(Надеюсь, я не открываю Америку с нуля)
Любая помощь очень ценится.