Saltar al contenido

Representación de doble precisión (64 bits) del valor numérico en R (signo, exponente, significado)

Después de investigar con especialistas en el tema, programadores de diversas áreas y maestros dimos con la respuesta al dilema y la compartimos en esta publicación.

Solución:

La respuesta a la pregunta planteada por @chux en los comentarios es “sí”; R apoya el %a formato:

sprintf("%a", 0.1)
#> [1] "0x1.999999999999ap-4"

Si desea acceder al patrón de bits subyacente, deberá reinterpretar el doble como un entero de 64 bits. Para esta tarea se puede usar C++ a través de Rcpp:

Rcpp::cppFunction('void print_hex(double x) 
    uint64_t y;
    static_assert(sizeof x == sizeof y, "Size does not match!");
    std::memcpy(&y, &x, sizeof y);
    Rcpp::Rcout << std::hex << y << std::endl;
', plugins = "cpp11", includes = "#include ")
print_hex(0.1)
#> 3fb999999999999a

Esta representación hexadecimal es idéntica a su representación binaria. ¿Cómo se llega a la representación decimal?

  • El primer bit es cero, por lo que el signo es positivo.
  • El exponente es 0x3fb, es decir, 1019 en decimal. Dado el sesgo del exponente, esto corresponde a un exponente real de -4.
  • La mantisa es 0x1999999999999a × 2^-52 incluyendo el 1 implícito, es decir, 2^−52 × 7,205,759,403,792,794.
  • En total, esto da 2^−56 × 7205759403792794:

    sprintf("%.60f", 2^-56 * 7205759403792794)
    #> [1] "0.100000000000000005551115123125782702118158340454101562500000"
    

De decimal a precio doble normalizado:

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

Por eso,

from10toNdp(0.1)
# "0011111110111001100110011001100110011001100110011001100110011010"

Ten en cuenta dar visibilidad a este post si te fue útil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *