Conversion to Binary and IEEE-754 Binary
06-27-2020, 01:35 PM
Post: #1
 Eddie W. Shore Senior Member Posts: 1,492 Joined: Dec 2013
Conversion to Binary and IEEE-754 Binary
Converting to Binary

The program BASE2 can convert any real number in Base 10 to Base 2. This extends on the built in base conversions, which works on integers only. BASE2 returns a string with precision up to 23 bits. Negative numbers will have the negative sign instead of a 2's compliment.

HP Prime Program BASE2

Code:
EXPORT BASE2(s) BEGIN // 2020-05-18 EWS // Decimal to Binary // for real x LOCAL str1,str2,str3; LOCAL d,u,w,k,x; x:=ABS(s); // set Binary mode, integer Base:=0; str1:=STRING(R→B(IP(x))); d:=DIM(str1); str1:=MID(str1,2,d-2); // fraction w:=FP(x); str2:="."; FOR k FROM 1 TO 25-d DO u:=IP(2*w); w:=FP(2*w); str2:=str2+STRING(u); END; // answer str3:=str1+str2; IF SIGN(s)==−1 THEN str3:="−"+str3; END; RETURN str3; END;

Examples:

BASE2(18.675) returns "10010.101011001100110011"

BASE2(-4.3825) returns "-100.01100001111010111000"

BASE2(π) returns "11.001001000011111101101"

Converting to IEEE-754 Format

The program IEEE754 converts any real number in decimal base to binary in IEEE-754 floating point format. A binary number in this format consists of a string of 32 bits:

Bit 1 is the sign bit: 1 for negative numbers, 0 for positive numbers

The next eight bits is the exponent bit: The exponent bit has a bias of 127. When converting to binary, 127 must be added to the exponent. (Example: 17 * 2^3. The exponent bit is 127 + 3 = 130). When converting to decimal, subtract 127 from the exponent word.

The last 23 bits consist of the mantissa.

The function returns a string with spaces between the sign, exponent, and mantissa sections for readability.

HP Prime Program IEEE754

Code:
EXPORT IEEE754(s) BEGIN // 2020-05-19 EWS // Decimal to IEEE 754 format // for real x LOCAL str1,str2,str3,str4,str5; LOCAL d,u,w,k,x,p; // determine sign bit x:=ABS(s); IF SIGN(s)==−1 THEN str1:="1"; ELSE str1:="0"; END; // set exponent // account for 127 bias // set Binary mode Base:=0; p:=127+IP(LOG(x)/LOG(2)); str2:=STRING(R→B(IP(p))); d:=DIM(str2)-2; str2:=MID(str2,2,d); // fill 0s for p<127 IF d<8 THEN FOR k FROM 1 TO 8-d DO str2:="0"+str2; END; END; // convert integer of mantissa str3:=STRING(R→B(IP(x))); d:=DIM(str3)-2; // account for # and b str3:=MID(str3,2,d); // convert fraction of matissa w:=FP(x); str4:=""; FOR k FROM 1 TO 23-d DO u:=IP(2*w); w:=FP(2*w); str4:=str4+STRING(u); END; // answer  // add spaces for clarity str5:=str1+" "+ str2+" "+ str3+str4; // RETURN {str1,str2,str3,str4,str5}; RETURN str5; END;

Example:

IEEE754(2100) returns "0 10001010 100000110100000000000000"

2100 -> 100000110100_2 -> 1.00000110100_2 * (2_10) ^ (11_10)
"moving the decimal point left 11 spaces"
Exponent bit: 127 + 11 = 138 (138_10 -> 10001010_2)

IEEE754(28.725) returns "0 10000011 11100101110011001100110"

IEEE754(-19.5) returns "1 10000011 10011100000000000000000"

Source:

Sivaraman, Abishalini. "Decimal to IEEE 754 Floating Pont Representation" YouTube Video Published December 4, 2016 https://www.youtube.com/watch?v=8afbTaA-...4_mdWQE84q

Petryk, Steve. "HOW TO: Convert Decimal to IEEE-754 Single-Precision Binary" YouTube Video. Published October 25, 2015. https://www.youtube.com/watch?v=tx-M_rqhuUA

06-27-2020, 08:37 PM (This post was last modified: 06-29-2020 12:12 PM by Albert Chan.)
Post: #2
 Albert Chan Senior Member Posts: 2,231 Joined: Jul 2018
RE: Conversion to Binary and IEEE-754 Binary
(06-27-2020 01:35 PM)Eddie W. Shore Wrote:  BASE2 returns a string with precision up to 23 bits.
...
BASE2(π) returns "11.001001000011111101101"

IEEE-754 single precision has 24-bits precision, not 23.
To complement IEEE754(), may be a good idea to match it.

BASE2(π) → ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿11.001001 00001111 11011011
IEEE754(π) → 01000000 01001001 00001111 11011011

Quote:IEEE754(2100) returns "0 10001010 100000110100000000000000"
IEEE754(28.725) returns "0 10000011 11100101110011001100110"
IEEE754(-19.5) returns "1 10000011 10011100000000000000000"

All 3 examples were wrong. Using online float-converter, you should get this instead:

IEEE754( 2100 ) = 01000101 00000011 01000000 00000000
IEEE754(28.725) = 01000001 11100101 11001100 11001101
IEEE754(-19.5 ) = 11000001 10011100 00000000 00000000

(06-27-2020 01:35 PM)Eddie W. Shore Wrote:  Sivaraman, Abishalini. "Decimal to IEEE 754 Floating Pont Representation" YouTube Video Published December 4, 2016 https://www.youtube.com/watch?v=8afbTaA-...4_mdWQE84q

Petryk, Steve. "HOW TO: Convert Decimal to IEEE-754 Single-Precision Binary" YouTube Video. Published October 25, 2015. https://www.youtube.com/watch?v=tx-M_rqhuUA

Both videos does not take into account of rounding-to-nearest, for the last bit.
Using Steve example, for x = 45.45

gcc:1> float x = 45.45f ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿/* suffix f required, otherwise value implicitly converted to double, back to float */
gcc:2> X(*(unsigned*) &x)
0x4235cccd

Repeating bits 0xcccc ... should rounded-up to 0xcccd

---

If conversions were done in binary, there is also a possibility of double-rounding errors.

>>> import gmpy2
>>> x = gmpy2.mpfr('0.50000020861625671')
>>> print format(x,'a') ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿# rounded 53 bits
0x8.000038p-4

Converting to double precision, x = 0x0.8000037fffffffb8... , got rounded-up.
This happens to be half-way case for single-precision, which got rounded-up again.

>>> b = 2**(53-24)-1
>>> print format(x+b-b,'a') ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿# rounded 24 bits
0x8.00004p-4

Many online float converters got this one wrong: 0x0.800004
Above converter work very well, and got it right: 0x0.800003

Doing by hand, just scale the number to 24 bits:

0.5000002086162567 = 8388611.4999999997673472 / 2^24

Round-to-nearest, we have 8388611/2^24 = 0x800003p-24 = 0x0.800003

Or, you can try the decimal/binary converter

0.5000002086162567 = 0b0. 10000000 00000000 00000011 01111111...
06-29-2020, 01:33 PM
Post: #3
 Albert Chan Senior Member Posts: 2,231 Joined: Jul 2018
RE: Conversion to Binary and IEEE-754 Binary
(06-27-2020 01:35 PM)Eddie W. Shore Wrote:  Bit 1 is the sign bit: 1 for negative numbers, 0 for positive numbers
The next eight bits is the exponent bit: The exponent bit has a bias of 127 ...
The last 23 bits consist of the mantissa.

Another interpretation is to think of exponents field and the mantissa overlapped on the imply bit.
For IEEE single, instead of bias of 127, do offset 126

Example: x = 2100 = 1.025390625 * 2^11 = 0b1.000001101 * 2^(0b10001001 - 126)

Code:
sign = 0 bexp =  1000100 1 mant =          10000011 01000000 00000000   ; upto 24 bits precision SUM  = 01000101 00000011 01000000 00000000   ; bits for 2100.f

This has the advantage of extending conversion to sub-normal, without special treatment.
(i.e. when mantissa cannot converted to pattern 1.xxx ..., with bexp already reached 0)

Example: x = 1e-40f ≈ 71362.38 / 2^149. Since 71362 < 2^24, bexp = 0

→ bits = 71362 = 0b 00000000 00000001 00010110 11000010

gcc:1> unsigned u = 71362
gcc:2> G(*(float*) &u)
9.9999461011147596e-041
gcc:3> G(1e-40f) ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿ ﻿/* confirm */
9.9999461011147596e-041
06-29-2020, 01:58 PM
Post: #4
 Eddie W. Shore Senior Member Posts: 1,492 Joined: Dec 2013
RE: Conversion to Binary and IEEE-754 Binary
Albert,

I reverted the post to draft status (the entry is not live on my blog), I am going to take a look at the code again. Thank you for bringing this to my attention.

Eddie
08-02-2020, 02:51 PM (This post was last modified: 08-02-2020 02:52 PM by Eddie W. Shore.)
Post: #5
 Eddie W. Shore Senior Member Posts: 1,492 Joined: Dec 2013
RE: Conversion to Binary and IEEE-754 Binary
Here is my second attempt at it, except I just concentrated at the conversion to binary, with a user-given precision level.

To help with rounding the number, I first round the number to the nearest 1/2^n, then convert the result to binary.

I have not retried the IEEE-754 yet.

The program RBIN converts any real number in base 10 to base 2, including non-integers and negative numbers. The result is displayed as a string.

RBIN will need two arguments: the number to be converted and the precision level.

For the precision level:

1 rounds the number to the nearest 1/2 before conversion.

2 rounds the number to the nearest 1/4 before conversion.

3 rounds the number to the nearest 1/8 before conversion.

4 rounds the number to the nearest 1/16 before conversion.

and so on.

HP Prime Program: RBIN

Code:
EXPORT RBIN(x,p) BEGIN // 2020-07-11 EWS // Decimal to Binary // decimal, precision // for real x, rounded 1/2^p LOCAL b,i,f,n,s,w,k,str; s:=ABS(x); b:=IP(s)+ROUND(FP(s)*2^p,0)/2^p; str:=""; i:=IP(b); f:=FP(b); IF i≠0 THEN n:=IP(LOG(i)/LOG(2)); FOR k FROM n DOWNTO 0 STEP 1 DO w:=IP(i/2^k); str:=str+STRING(w); i:=i-w*2^k;  END; END; IF f≠0 THEN str:=str+"."; FOR k FROM 0 TO p-1 DO w:=IP(2*f); str:=str+STRING(w); f:=FP(2*f); END; END; IF x<0 THEN str:="-"+str; END; RETURN str; END;

Examples:

RBIN(-0.985,3) returns "-1"
RBIN(-0.985,6) returns "-.111111"
RBIN(-0.985,9) returns "-.111111000"

RBIN(860.63,3) returns "1101011100.101"
RBIN(860.63,6) returns "1101011100.101000"
RBIN(860.63,9) returns "1101011100.101000011"