如何将数值转换为内存中的规范化双精度,反之亦然?
How to convert numeric value to normalized double precision in memory and vice versa in R?
我的主要目标是编写一个函数来转换:
- (十进制)数值到内存中的归一化双精度
- 内存中标准化双精度为(十进制)数值
即
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 的整数(即它也适用于存储为双精度的整数;适用于超过 2147483647 的整数);对于大于 2^53 的数字,它开始丢失数字。
EXAMPLE1: 将 0.3 转换为 64 位归一化双精度数:
符号:0:正; 1:negative
sprintf("%a", 0.3) # ("0x1.3333333333333p-2")16
library(BMS)
BMS::hex2bin("3333333333333") # (0011001100110011001100110011001100110011001100110011)2=significand=(3333333333333)16
由于sprintf
的输出最后三个"p-2"和"BiasedExponent=RealExponent+1023bias"(偏差:2^(11-1)-1 = 1023),指数(11位)是-2 +1023=1021.
from10to2(1021) # ("01111111101")2
双精度存储:
0 | 01111111101 | 0011001100110011001100110011001100110011001100110011
标志 |指数 |有效数
EXAMPLE2: 将 -2.94 转换为 64 位规范化双精度数:
符号:0:正; 1:negative
sprintf("%a", -2.94) # "-0x1.7851eb851eb85p+1"
library(BMS)
BMS::hex2bin("7851eb851eb85") # (0111100001010001111010111000010100011110101110000101)2=significand=(7851eb851eb85)16
由于sprintf
输出的最后三个"p+1"和"BiasedExponent=RealExponent+1023bias"(bias:2^(11-1)-1 = 1023),指数(11bit)为1+ 1023=1024.
from10to2(1024) # ("10000000000")2
双精度存储:
1 | 10000000000 | 0111100001010001111010111000010100011110101110000101
标志 |指数 |有效数
EXAMPLE3: 将 86.125 转换为 64 位规范化双精度数:
符号:0:正; 1:negative
sprintf("%a", 86.125) # "0x1.588p+6"
library(BMS)
BMS::hex2bin("588") # (010110001000)2=significand=(588)16
由于sprintf
输出的最后三个"p+6"和"BiasedExponent=RealExponent+1023bias"(bias:2^(11-1)-1 = 1023),指数(11bit)为6+ 1023=1029.
from10to2(1029) # ("10000000101")2
双精度存储:
0 | 10000000101 | 010110001000(但这不是64位,而是1+11+12=24位!)
标志 |指数 |有效数。
真正的 64 位双精度必须是:
0 | 10000000101 | 010110001000000000000000000000000000000000000000000.
因此,此方法无法找到最后 40 个零,但可以正确找到前 24 位。
在线转换器:
- https://www.exploringbinary.com/floating-point-converter/
"Raw Binary (sign field | exponent field | significand field) Double:"
- http://www.binaryconvert.com/convert_double.html
我的技术(适用于 0.3 和 -2.94)意外地停止了 86.125 的功能并且不产生 64 位。
为什么该技术在 86.125 时停止?
是否已经有转换的方法:
- (十进制)数值到内存中的归一化双精度
- 内存中的规范化双精度为(十进制)数值?
(我希望我所做的不是从头开始重新发现美国)
非常感谢任何帮助。
library(BMS)
from10toNdp <- function(my10baseNumber) {
out <- list()
# Handle special cases (0, Inf, -Inf)
if (my10baseNumber %in% c(0,Inf,-Inf)) {
if (my10baseNumber==0) { out <- "0000000000000000000000000000000000000000000000000000000000000000" }
if (my10baseNumber==Inf) { out <- "0111111111110000000000000000000000000000000000000000000000000000" }
if (my10baseNumber==-Inf) { out <- "1111111111110000000000000000000000000000000000000000000000000000" }
} else {
signBit <- 0 # assign initial value
from10to2 <- function(deciNumber) {
binaryVector <- rep(0, 1 + floor(log(deciNumber, 2)))
while (deciNumber >= 2) {
theExpo <- floor(log(deciNumber, 2))
binaryVector[1 + theExpo] <- 1
deciNumber <- deciNumber - 2^theExpo }
binaryVector[1] <- deciNumber %% 2
paste(rev(binaryVector), collapse = "")}
#Sign bit
if (my10baseNumber<0) { signBit <- 1
} else { signBit <- 0 }
# Biased Exponent
BiasedExponent <- strsplit(from10to2(as.numeric(substr(sprintf("%a", my10baseNumber), which(strsplit( sprintf("%a", my10baseNumber), "")[[1]]=="p")+1, length( strsplit( sprintf("%a", my10baseNumber), "")[[1]]))) + 1023), "")[[1]]
BiasedExponent <- paste(BiasedExponent, collapse='')
if (nchar(BiasedExponent)<11) {BiasedExponent <- paste(c( rep(0,11-nchar(BiasedExponent)), BiasedExponent),collapse='') }
# Significand
significand <- BMS::hex2bin(substr( sprintf("%a", my10baseNumber) , which(strsplit( sprintf("%a", my10baseNumber), "")[[1]]=="x")+3, which(strsplit( sprintf("%a", my10baseNumber), "")[[1]]=="p")-1))
significand <- paste(significand, collapse='')
if (nchar(significand)<52) {significand <- paste(c( significand,rep(0,52-nchar(significand))),collapse='') }
out <- paste(c(signBit, BiasedExponent, significand), collapse='')
}
out
}
from10toNdp(0.3)
# "0011111111010011001100110011001100110011001100110011001100110011"
from10toNdp(-2.94)
# "1100000000000111100001010001111010111000010100011110101110000101"
from10toNdp(86.125)
# "0100000001010101100010000000000000000000000000000000000000000000"
from10toNdp(-589546.684259)
# "1100000100100001111111011101010101011110010101110011001000010110"
from10toNdp(0)
# "0000000000000000000000000000000000000000000000000000000000000000"
from10toNdp(Inf)
# "0111111111110000000000000000000000000000000000000000000000000000"
from10toNdp(-Inf)
# "1111111111110000000000000000000000000000000000000000000000000000"
我的主要目标是编写一个函数来转换:
- (十进制)数值到内存中的归一化双精度
- 内存中标准化双精度为(十进制)数值
即
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 的整数(即它也适用于存储为双精度的整数;适用于超过 2147483647 的整数);对于大于 2^53 的数字,它开始丢失数字。
EXAMPLE1: 将 0.3 转换为 64 位归一化双精度数:
符号:0:正; 1:negative
sprintf("%a", 0.3) # ("0x1.3333333333333p-2")16
library(BMS)
BMS::hex2bin("3333333333333") # (0011001100110011001100110011001100110011001100110011)2=significand=(3333333333333)16
由于sprintf
的输出最后三个"p-2"和"BiasedExponent=RealExponent+1023bias"(偏差:2^(11-1)-1 = 1023),指数(11位)是-2 +1023=1021.
from10to2(1021) # ("01111111101")2
双精度存储:
0 | 01111111101 | 0011001100110011001100110011001100110011001100110011
标志 |指数 |有效数
EXAMPLE2: 将 -2.94 转换为 64 位规范化双精度数:
符号:0:正; 1:negative
sprintf("%a", -2.94) # "-0x1.7851eb851eb85p+1"
library(BMS)
BMS::hex2bin("7851eb851eb85") # (0111100001010001111010111000010100011110101110000101)2=significand=(7851eb851eb85)16
由于sprintf
输出的最后三个"p+1"和"BiasedExponent=RealExponent+1023bias"(bias:2^(11-1)-1 = 1023),指数(11bit)为1+ 1023=1024.
from10to2(1024) # ("10000000000")2
双精度存储:
1 | 10000000000 | 0111100001010001111010111000010100011110101110000101
标志 |指数 |有效数
EXAMPLE3: 将 86.125 转换为 64 位规范化双精度数:
符号:0:正; 1:negative
sprintf("%a", 86.125) # "0x1.588p+6"
library(BMS)
BMS::hex2bin("588") # (010110001000)2=significand=(588)16
由于sprintf
输出的最后三个"p+6"和"BiasedExponent=RealExponent+1023bias"(bias:2^(11-1)-1 = 1023),指数(11bit)为6+ 1023=1029.
from10to2(1029) # ("10000000101")2
双精度存储:
0 | 10000000101 | 010110001000(但这不是64位,而是1+11+12=24位!)
标志 |指数 |有效数。
真正的 64 位双精度必须是:
0 | 10000000101 | 010110001000000000000000000000000000000000000000000.
因此,此方法无法找到最后 40 个零,但可以正确找到前 24 位。
在线转换器:
- https://www.exploringbinary.com/floating-point-converter/
"Raw Binary (sign field | exponent field | significand field) Double:" - http://www.binaryconvert.com/convert_double.html
我的技术(适用于 0.3 和 -2.94)意外地停止了 86.125 的功能并且不产生 64 位。
为什么该技术在 86.125 时停止?
是否已经有转换的方法:
- (十进制)数值到内存中的归一化双精度
- 内存中的规范化双精度为(十进制)数值?
(我希望我所做的不是从头开始重新发现美国)
非常感谢任何帮助。
library(BMS)
from10toNdp <- function(my10baseNumber) {
out <- list()
# Handle special cases (0, Inf, -Inf)
if (my10baseNumber %in% c(0,Inf,-Inf)) {
if (my10baseNumber==0) { out <- "0000000000000000000000000000000000000000000000000000000000000000" }
if (my10baseNumber==Inf) { out <- "0111111111110000000000000000000000000000000000000000000000000000" }
if (my10baseNumber==-Inf) { out <- "1111111111110000000000000000000000000000000000000000000000000000" }
} else {
signBit <- 0 # assign initial value
from10to2 <- function(deciNumber) {
binaryVector <- rep(0, 1 + floor(log(deciNumber, 2)))
while (deciNumber >= 2) {
theExpo <- floor(log(deciNumber, 2))
binaryVector[1 + theExpo] <- 1
deciNumber <- deciNumber - 2^theExpo }
binaryVector[1] <- deciNumber %% 2
paste(rev(binaryVector), collapse = "")}
#Sign bit
if (my10baseNumber<0) { signBit <- 1
} else { signBit <- 0 }
# Biased Exponent
BiasedExponent <- strsplit(from10to2(as.numeric(substr(sprintf("%a", my10baseNumber), which(strsplit( sprintf("%a", my10baseNumber), "")[[1]]=="p")+1, length( strsplit( sprintf("%a", my10baseNumber), "")[[1]]))) + 1023), "")[[1]]
BiasedExponent <- paste(BiasedExponent, collapse='')
if (nchar(BiasedExponent)<11) {BiasedExponent <- paste(c( rep(0,11-nchar(BiasedExponent)), BiasedExponent),collapse='') }
# Significand
significand <- BMS::hex2bin(substr( sprintf("%a", my10baseNumber) , which(strsplit( sprintf("%a", my10baseNumber), "")[[1]]=="x")+3, which(strsplit( sprintf("%a", my10baseNumber), "")[[1]]=="p")-1))
significand <- paste(significand, collapse='')
if (nchar(significand)<52) {significand <- paste(c( significand,rep(0,52-nchar(significand))),collapse='') }
out <- paste(c(signBit, BiasedExponent, significand), collapse='')
}
out
}
from10toNdp(0.3)
# "0011111111010011001100110011001100110011001100110011001100110011"
from10toNdp(-2.94)
# "1100000000000111100001010001111010111000010100011110101110000101"
from10toNdp(86.125)
# "0100000001010101100010000000000000000000000000000000000000000000"
from10toNdp(-589546.684259)
# "1100000100100001111111011101010101011110010101110011001000010110"
from10toNdp(0)
# "0000000000000000000000000000000000000000000000000000000000000000"
from10toNdp(Inf)
# "0111111111110000000000000000000000000000000000000000000000000000"
from10toNdp(-Inf)
# "1111111111110000000000000000000000000000000000000000000000000000"