Hola usuario de nuestro sitio web, hemos encontrado la solución a lo que andabas buscando, has scroll y la encontrarás más abajo.
Solución:
editar (2017) de la segunda mitad de la respuesta: desde octubre de 2014, esta parte de la respuesta se rompió debido a una redefinición en xint 1.1
de xintFloor
cuyo significado original, como se usa aquí, ahora está en una macro llamada xintiFloor
. También comportamiento de xintFloat
cambió un poco en xint 1.2k (2017/01/06)
para el caso de redondeo a una potencia de diez, la imagen de salida tuvo que actualizarse.
De hecho, se puede definir un comando y automatizar un poco.
documentclassarticle
usepackagexinttools
newcounterbitindex
newcommandbitpicture [3]%
setlengthunitlength1mm
setlengthfboxsep0mm
beginpicture(130,16)
% sign bit
put(2,4)framebox(4,8)#1
% exponent
setcounterbitindex1%
xintFor* ##1 in #2
do
put(numexpr 2+4*valuebitindex,4)framebox(4,8)##1%
stepcounterbitindex%
% fraction
setcounterbitindex1%
xintFor* ##1 in #3
do
put(numexpr 34+4*valuebitindex,4)framebox(4,8)##1%
stepcounterbitindex%
% upper labels
put(0,14)scriptsizeMSB
put(126,14)scriptsizeLSB
%lower labels
put(3,0)scriptsizeS
put(7,0)line(0,1)2
put(7,1)vector(1,0)8
put(16,0)scriptsizeExponent
put(37,1)vector(-1,0)8
put(37,0)line(0,1)2
put(39,0)line(0,1)2
put(39,1)vector(1,0)38
put(79,0)scriptsizeFraction
put(130,1)vector(-1,0)38
put(130,0)line(0,1)2
endpicture%
begindocument
beginfigure
centering
bitpicture 01000000010010010000111111010000
captionThe value 3.14159 stored as a textttfloat.
labelfigure:pi_example
endfigure
enddocument
Además, podría ser posible calcular la representación binaria a partir de la decimal (si alguien me explica la regla, puedo implementarla).
Como complemento, aquí hay un código para convertir en Double Binary (ver wikipedia). Al ingresar cualquier cosa aceptable por las macros de xintfrac, al generar el formato binario doble en 64
bits, en tres macros BDsign
, BDexponent
, BDfraction
. Como la entrada puede tener cientos de dígitos, primero se convierte en un decimal flotante con 24
precisión de dígitos. La conversión a doble binario se realiza desde ese punto de partida con 24
dígitos decimales y una potencia de diez exponente (observe que xint
permite todo el camino hasta 10^2147483647
, así el código trata NaN
y también se ocupa de los números por debajo de lo normal). También hay una macro que va en sentido inverso.
Naturalmente, esto solo ilustra la conversión implementada aquí, conversión cuyos pasos se explican en los comentarios del código.
los bitpicture
del código anterior podría rehacerse para el 64
caso de bits, solo es necesario cambiar algunas cosas y bitpictureBDsignBDexponentBDfraction
trabajaría. Pero aquí elegí una representación en línea más simple.
documentclassarticle
usepackagexintfrac
usepackagexintbinhex
usepackagexintexpr
usepackagecolor
usepackage[paperheight=50cm,vscale=0.9,hscale=0.72]geometry
makeatletter
newcommandToDouble[1]%
% This commands handles arbitrary expandable material producing
% an input number in the formats as understood by xint: integers,
% fractions, decimal numbers, scientific notation, or fractions with such
% numbers etc... for example 12.34, or 1.07/3.25 or 12e7, or
% 1.25e7/3.12e5
% It computes the Double Precision Binary representation and puts the
% 64 binary digits in the three macros BDsign (1bit), BDexponent
% (11bit), BDfraction (52bit)
edef[email protected]
#1%
% Then we convert #1 to float with 24 digits of precision, this step
% is in case
% we have some very long input like pi with 1000 digits for example.
% We don't want to have to do computations with that many digits
% aftewards.
% (oodef = def with twice expansion of the contents)
% 24 digits is overkill.
oodef[email protected] xintFloat [24][email protected]%
xintifSgn [email protected]
defBDsign 1oodef[email protected] xintAbs [email protected][email protected]
defBDsign 0defBDexponent00000000000%
defBDfraction0000000000000000000000000000000000000000000000000000
defBDsign 0[email protected] %
%
def[email protected]@t #1[#2]def[email protected] #2%
def[email protected] %
% first we get the power of 10 such that 10^t <= x < 10^t+1
% this is done by converting to float with 1 digit of precision.
% XINTinFloat will produce d[t], with 1<= d <= 10 (10 is obtained
% only from upper rounding, for example 9.95 becomes 10[0])
% Note that t may be as big as 2147483647 which is way beyond
% what can be represented as a double
oodef[email protected] XINTinFloat [1][email protected]%
expandafter[email protected]@t[email protected]
% What we really want is exponent of a power of two which is about
% 3.32 times t:
% 1/log10(2) = 3.3219280948873623478703194294...
% we don't need that much precision as allowable range of decimal exponents
% (single precision) from -38 to +38 for normal and -45 to -38 for
% subnormal numbers
% (double precision) from -324 to +308
% we thus take a lower bound, and then multiply by 2 or divide by 2 the
% number of times (3 or perhaps 4 times at most) to end up in the correct
% range 1<= f <2. We will then need to check for subnormal numbers.
% to reduce overhead in handling of y, we first check the size of t:
xintifGt [email protected]1000
% too big number (10^1000)
defBDexponent 11111111111%
defBDfraction
1000000000000000000000000000000000000000000000000000%
[email protected] %
xintifLt [email protected]-1000
% too close to zero number (10^-1000)
defBDexponent 00000000000%
defBDfraction
0000000000000000000000000000000000000000000000000000%
[email protected] %
% we are now guaranteed that [email protected] will be usable with numexpr,
% let's get it:
% (since 1.1 we need to use xintiFloor to get an integer,
% as xintFloor adds a trailing /1[0] for better efficiency
% in chaining xintfrac.sty macros)
oodef[email protected] xintiFloor xintMul 3.321928[email protected]%
% below apart from the float computation of the power of 2,
% the other operations are handled exactly
% (xintDiv does not do much as xint handles fractions natively,
% it just prepares a fraction)
% (the real work will be done by the comparison tests)
oodef[email protected] xintDiv [email protected]xintFloatPow [24]2[email protected]%
%
xintloop
xintifLt [email protected]1
oodef[email protected] xintMul 2[email protected]%
odef[email protected] thenumexpr [email protected]%
iftrue %
iffalse % stop the loop if z >= 1
repeat
%
xintloop
xintifLt [email protected]2
iffalse % stop the loop if z < 2
oodef[email protected] xintDiv [email protected]2%
odef[email protected] thenumexpr [email protected]+1%
iftrue %
repeat
%
odef [email protected] thenumexpr 1023+[email protected] % biased exponent
% We need to check if we have a sub-normal number or NaN
ifnum [email protected] > 2046 % beyond allowable range of double precision
defBDexponent 11111111111%
defBDfraction 1000000000000000000000000000000000000000000000000000%
else
ifnum [email protected] < 1
% sub-normal number
% x is theoretically less than 2^-1022
% however with the computations giving the z such that 1<= z < 2
% z is only an approximation to x 2^(-y)
% Thus it could be that the x is in fact 2^-1022 or slightly
% greater and should then be represented as a normal number
% we forget about the computed z and work again starting from x
% We multiply x by 2^1022+52=2^1074
% 2^1074=2.024022533073106183524953467.. 10^323
% keep it with 24 digits precision -> 202402253307310618352495[300]
% then we round to the nearest integer and
% later we test to check if we have something too big
oodef[email protected]
xintiRound0 xintMul [email protected]202402253307310618352495[300]%
%
xintifGt[email protected]4503599627370495
% 2^52= 4503599627370496
% we have in fact a normal number between 2^-1022 and 2^-1021
defBDexponent 00000000001%
oodef[email protected] xintDecToBin [email protected]%
% we gobble the first 1 of the 53bit representation to get 52 bits.
oodefBDfraction expandafter@gobble[email protected] %
%
% we really have a sub-normal number
defBDexponent 00000000000%
% we add 2^52, convert to binary, gobble the first 1.
oodef[email protected] xintDecToBin xintiiAdd 4503599627370496[email protected]%
oodefBDfraction expandafter@gobble[email protected] %
%
else
% 1<= e <= 2046: normal case
% 1<= z < 2 holds for the fraction part.
% We multiply by 2^52= 4503599627370496,
% round, convert to binary, and gobble the first 1.
% However rounding may have been up to 2^53, thus we test for
% that case and then use rather 2^53-1.
%
oodef [email protected] xintiRound0 xintMul 4503599627370496[email protected]%
%
xintifEq [email protected]9007199254740992
defBDfraction
1111111111111111111111111111111111111111111111111111%
% convert to binary and gobble the first 1 of the 53bit
% representation
oodef[email protected] xintDecToBin [email protected]%
oodefBDfraction expandafter@gobble[email protected] %
% end of BDfraction computation
% we also need the biased exponent in 11bit binary
%
oodef [email protected] xintDecToBin thenumexpr 2048+[email protected]relax%
oodef BDexponent expandafter@gobble[email protected] %
fi
fi
relax
%
def[email protected] #1relax
% the decimal float evaluation will be made with current value of
% xintDigits, and printed according to the optional parameter
newcommandPrintAsDecimalFloat [4][16]%
edef[email protected]#2%
edef[email protected]#3%
edef[email protected]#4%
if1[email protected]fi
def[email protected]11111111111%
ifx[email protected][email protected]
xintifZero [email protected]inftyNaN%
else
def[email protected]00000000000%
ifx[email protected][email protected]
xintFloat [#1]
xintthefloatexpr 2^(-1074)*xintBinToDec[email protected]relax%
else
% inserts a leading 1
odef[email protected] expandafter1[email protected]%
xintFloat [#1]
xintthefloatexpr
2^(xintBinToDec[email protected])*
(xintBinToDec[email protected]/2^52)relax%
fi
fi
makeatother
newcommandPrintCurrentDouble
BDsign
xintifZeroBDexponenttextcolorred
xintifEqBDexponent11111111111textcolorredtextcolorblue%
BDexponent%
BDfraction
newcommandCurrentDoubleAsDecimalFloat
xintDigits:=18;PrintAsDecimalFloatBDsignBDexponentBDfraction
newcommandTest [1]textttdetokenize#1
(xintFloat [16]#1)newlineToDouble#1
PrintCurrentDouble
$to$CurrentDoubleAsDecimalFloat par
begindocument
First line of each paragraph shows the number as input to the conversion
routine, then within parentheses its conversion to a decimal floating
number with 16 digits of precision, then on the next line the 64bit
double representation and next the reconstructed number
as a floating decimal evaluated with 18 digits of precision and printed
with 16.
% This comment of original answer is false since xint 1.2k (2017/01/06):
% %% Notice that verb|xintFloat| outputs verb|10.000..00eN| when
% %% the rounding went up.
% Policy was modified at xint 1.2k and output always has total of P digits
% with P the floating point precision: so 1.00..., not 10.00...
Test3.14159
Test-3.14159
Test3.14159265
Test3.141592653590
Test3.14159265358979324
Test1[-20]
Test1[-200]
Test1.2345678987654321e-304
Test1.2345678987654321e-312
Test1.2345678987654321e-320
Test1[-400]
Test-1[-2000]
Test1[20]
Test1[200]
Test1[400]
Test1[2000]
Testxinttheiexpr 2^50relax
Testxinttheiexpr 2^100relax
Testxinttheiexpr 2^150relax
Testxinttheiexpr 2^200relax
Test1234/4567
We also obtain, computing with 18 decimal digits and printing 17:
xintDigits := 18;
begintabularrl
minimal subnormal double&
PrintAsDecimalFloat [17]
0000000000000000000000000000000000000000000000000000000000000001\
maximal subnormal double&
PrintAsDecimalFloat [17]
0000000000001111111111111111111111111111111111111111111111111111\
minimal normal double&
PrintAsDecimalFloat [17]
0000000000010000000000000000000000000000000000000000000000000000\
maximal normal double&
PrintAsDecimalFloat [17]
0111111111101111111111111111111111111111111111111111111111111111\
endtabular
enddocument
En caso de que no lo sepa, el paquete de campo de bytes se puede utilizar para escribir valores binarios. Su objetivo principal es dibujar campos de datos de protocolo, pero se puede utilizar para cualquier tipo de campo de datos.
Simplemente escribe lo que quieras, pero no puedes usarlo para convertir de binario a decimal como propone jbfu con su gran paquete xint.
Un pequeño ejemplo con bytefield
documentclassarticle
usepackagebytefield
usepackagexcolor
usepackagegraphicx
newcommandcolorbitbox[3]%
rlapbitbox#2color#1rulewidthheight%
bitbox#2#3
definecolorlightcyanrgb0.84,1,1
definecolorlightgreenrgb0.64,1,0.71
definecolorlightredrgb1,0.7,0.71
begindocument
textttbytefield package helps you to draw data fields.
begincenter
beginbytefield[bitheight=widthof~Sign~,
boxformatting=centeringsmall]32
bitheader[endianness=big]31,23,0 \
colorbitboxlightcyan1rotatebox90Sign &
colorbitboxlightgreen8Exponent &
colorbitboxlightred23Mantissa
endbytefield
endcenter
You can also fill specify every bit
begincenter
beginbytefield[bitheight=widthof~Sign~,
boxformatting=centeringsmall]32
bitheader[endianness=big]31,23,0 \
colorbitboxlightcyan10 &
colorbitboxlightgreen11 &
colorbitboxlightgreen10 &
colorbitboxlightgreen10 &
colorbitboxlightgreen10 &
colorbitboxlightgreen10 &
colorbitboxlightgreen10 &
colorbitboxlightgreen10 &
colorbitboxlightgreen10 &
colorbitboxlightred11 &
colorbitboxlightred11 &
colorbitboxlightred11 &
colorbitboxlightred11 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
colorbitboxlightred10 &
endbytefield
endcenter
or use an hexadecimal format to simplify typping
begincenter
beginbytefield[bitheight=widthof~Sign~,
boxformatting=centeringsmall]32
bitheader[endianness=big]31,30,23,22,0 \
colorbitboxlightcyan10 &
colorbitboxlightgreen80x80 &
colorbitboxlightred230x7A0800\
bitbox[]1rotatebox90Sign & bitbox[]8Exponent & bitbox[]23Mantissa\
endbytefield
endcenter
enddocument
Si haces scroll puedes encontrar los informes de otros sys admins, tú igualmente eres capaz insertar el tuyo si lo deseas.