Register - Login
Views: 99852669
Main - Memberlist - Active users - Calendar - Wiki - IRC Chat - Online users
Ranks - Rules/FAQ - Stats - Latest Posts - Color Chart - Smilies
05-04-22 11:09:30 AM
Jul - Computers and Technology - Half-Precision Floats to Hexadecimal ? New poll - New thread - New reply
Next newer thread | Next older thread
messiaen
Catgirl
Level: 68


Posts: 82/1085
EXP: 2596623
For next: 132177

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 05-13-08 01:45:10 PM Link | Quote
Hi, could someone point me to a program which converts Half-Precision (16 bit) Floats to Hexadecimal? I searched Google and could not find any program for this kind of operation.

This one can convert decimal to 32 and 64-bit floats and give the result in hex, but won't output it in half-precision.

I am searching this to be able to do correct texture coordinates on N64 and understand better values stored in floats.
neotransotaku
Member
wonders why OSX does not come with their version of MSPaint?
Level: 53


Posts: 280/603
EXP: 1084813
For next: 72306

Since: 08-24-07

From: The Landmark @ One Market

Since last post: 2.6 years
Last activity: 42 days

Posted on 05-13-08 05:23:59 PM Link | Quote
You need to know how a decimal number is encoded into a 16-bit float used in the N64: the number of bits used to hold the sign, exponent, and mantissa/fractional portion.

In 32-bit floating point, 1 bit used for sign, 8 bits used for biased exponent, and 23 bits for fractional portion. For example, 2.5 is encoded as 10.1 x 2^0 in binary, which becomes 1.01 x 2^1 to be a properly formatted binary notation, to become 0|1000 0000|0100 0000 0000 0000 0000 000 in binary encoded floating point number, to finally 0x4020 0000.
messiaen
Catgirl
Level: 68


Posts: 83/1085
EXP: 2596623
For next: 132177

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 05-13-08 06:41:44 PM Link | Quote
Thanks for your input. I don't have a background in computer science/programming, and while understanding conversions between binary/decimal/hex isn't very difficult, floats are still a mystery to me. For now, my initial aim is to understand how to represent simple integers in this 16-bit format. This is used for texture coordinates in Mario 64.

I probably will need to read much more about this, but let's see if a understood a bit of this. I want to find the decimal value of the 50DE (hex) 16-bit float. That in binary is "101000011011110" according to my Windows calculator .

This is the format used ("s10e5" ):

Sign bit: 1
Exponent width: 5
Significand precision: 10 (11 implicit)

1|01000|011011110

Did I do something wrong, why there is one missing bit? How do I proceed now to get my decimal value?
Hiryuu

Level: 207


Posts: 3205/14435
EXP: 127635843
For next: 2148311

Since: 07-06-07


Since last post: 11.8 years
Last activity: 11.7 years

Posted on 05-13-08 07:36:06 PM Link | Quote
Not that I can say much of anything in the field other than being able to convert to any given number base if I needed to...but are you sure it wasn't Windows missing the leading 0 out in front? I was pretty sure you had to traverse past 8000 for it to be negative...

Could be 0 | 10100 | 0011011110 that you're after (pretty sure it is).

As for decimals to the fullest on the format you described...goootttt me.

____________________
neotransotaku
Member
wonders why OSX does not come with their version of MSPaint?
Level: 53


Posts: 282/603
EXP: 1084813
For next: 72306

Since: 08-24-07

From: The Landmark @ One Market

Since last post: 2.6 years
Last activity: 42 days

Posted on 05-13-08 07:41:50 PM Link | Quote
if you use windows calc, turn on digit grouping It seems you are missing the leading digit. If you used digit grouping, you would have seen you had only 15 digits instead of the 16 required.

0101 0000 1101 1110 ==> 0|101 00|00 1101 1110 ==> 0 | 10100| 0011 0111 10

1.001101111 x 2^(20-15) ==> 1.001101111 x 2^5 ==> 100110.1111 ==> 38 + 15/16

100110 is the whole number part, which you can convert into binary
0.1111 is equivalent to 2^-1 + 2^-2 + 2^-3 + 2^-4, which equals 15/16

Some notes
+ If you had 0.1101, then its decimal conversion is 2^-1 + 2^-2 + 2^-4 or 11/16
+ If you interpreted the exponent bits as signed decimal, you have 20. Floating point exponents, for reasons you can find on wikipedia, are biased. As a result, you need to remove the bias to get the actual exponent. For a n-bit exponent, the bias is 2^(n-1) - 1. Thus, for 5-bits, it is 15.
GuyPerfect
Catgirl
Level: 68


Posts: 441/1096
EXP: 2665961
For next: 62839

Since: 07-23-07


Since last post: 1.7 years
Last activity: 220 days

Posted on 05-15-08 11:02:30 PM (last edited by GuyPerfect at 05-16-08 02:27 PM) Link | Quote
No sense in doing it the hard way. They call these floating-point for a reason. Just move the decimal point to convert from binary to decimal.

Example (32-bit):
Hex Value: BDAE147B
Binary Value: 1011 1101 1010 1110 0001 0100 0111 1011
Sign: 1 (Negative)
Exponent: 01111011 = 123 (decimal)
Signficand: 01011100001010001111011 = 3,019,899 (decimal)

-

To process the exponent, subtract the bias of 127. This allows for both positive and negative exponents. 123 - 127 = -4

-

To process the significand, shift the "binary decimal point" the same way you'd do it in decimal. To turn 456 into 45.6, you divide by 10, right? That's a 1 followed by 1 zero; the number of zeroes indicating the number of decimal places to shift.

In this example, we've got 23 bits of sigificand, which means that a binary number with 1 followed by 23 zeroes represents the number of binary digits to shift. The number comes out to 8,388,608 decimal.

PointShifter = 2 ^ SignificandBits

The decimal representation of the significand is 3,019,899. Divide that by 8,388,608 to create 0.36000001430511474609375 or thereabouts. Last, add 1 to that to make 1.36000001430511474609375

-

Use the fomula (-1 ^ Sign) * (2 ^ Exponent) * Significand to get the final value: -0.085000000894069671630859375... Or, as the original number was, -0.085

----------

In 32-bit floats, the exponent field is 8 bits and the bias is 127. In 64-bit floats, the exponent field is 11 bits and the bias is 1,023. The pattern here is that the bias is the halfth value of the total number of representable values by the field. 8 bits makes for 256 values, half of which is 128. Since the first value is 0, the halfth value is 127. Same with 11 bits: 2,048 values, 1,023 bias.

Bias = (2 ^ ExponentBits) / 2 - 1

That said, given the "s10e5" business... 5 bits stores 32 values, which would make the bias 15.

With 10 bits for the significand, the number to use shifting the decimal point is 1,024.

Hex Value: 50DE
Binary Value: 0101 0000 1101 1110
Sign: 0 (Positive)
Exponent: 10100 = 20; 20 - 15 = 5; 2 ^ 5 = 32
Significand: 0011011110 = 222; 222 / 1024 + 1 = 1.216796875

Final value: 38.9375
This value appears to be video-game-ish, since 0.9375 is exactly 15/16.
__________

Edit × 2:
A note on denormalized values... If the exponent field is stored as 0, don't subtract the bias: the number is denormalized. Instead, in this situation, the significand does not have an implicit 1 preceding the decimal point. It's 0.xxx, not 1.xxx. Simply sign the significand in this scanario.
messiaen
Catgirl
Level: 68


Posts: 86/1085
EXP: 2596623
For next: 132177

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 05-16-08 09:58:26 AM (last edited by messiaen at 05-16-08 09:03 AM) Link | Quote
Thanks for the help, I am beggining to understand this.

I am trying to calculate a few numbers but I still have some questions. I picked a few hex values from Wikipedia and tried to reach the decimal result. This one is quite easy:

Hex: 3C00
Binary: 0 | 01111 | 0000000000
Sign = 0 (Positive)
Exponent: 01111 = 15 ; (15 - 15) bias = 0 ; 2^0 = 1
Significand = 0 + 1 (implicit bit) = 1.

Final decimal result: 1 (exp) * 1 (significand) = 1

This one should come at 65504 (max value), but I'm not sure what is going wrong, because after (Exp) * (Sig) I don't get 65504.

Hex: 7BFF
0 | 11110 | 1111111111
Sign = 0 (Positive)
Exponent: (14 - 15) = 2 ^ (-1) = 0.2
Significand: 1023 / 1024 = 0.9990234375 + 1 (is this the "implicit bit"?) = 1.9990234375

neotransotaku
Member
wonders why OSX does not come with their version of MSPaint?
Level: 53


Posts: 286/603
EXP: 1084813
For next: 72306

Since: 08-24-07

From: The Landmark @ One Market

Since last post: 2.6 years
Last activity: 42 days

Posted on 05-16-08 10:11:16 AM Link | Quote
7BFF

0|11110|11 1111 1111

11110 = 30 ==> 30 - 15 = 15 (remember you read the exponent bits as unsigned integer)

2^15 * 1.9990234 = 65504
messiaen
Catgirl
Level: 68


Posts: 88/1085
EXP: 2596623
For next: 132177

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 05-16-08 12:13:00 PM Link | Quote
Ouch, I think I missed a bit when converting the exponent from bin -> dec.

Now I gotta figure what is the easiest way to start from decimal and go to this especific float format hex. For instance, what about if I want to find the hex values for integers such as 2, 3, 4 ? This is what the calculator in my first post does, but only for 32 and 64-bit floats.
neotransotaku
Member
wonders why OSX does not come with their version of MSPaint?
Level: 53


Posts: 288/603
EXP: 1084813
For next: 72306

Since: 08-24-07

From: The Landmark @ One Market

Since last post: 2.6 years
Last activity: 42 days

Posted on 05-16-08 12:49:44 PM Link | Quote
just reverse the process:

+ to find the exponent, floor(log2(decimal number))

so, floor(log2(65504)) == floor(15.999295) == 15

+ find the significand

2^15 = 32768 ==> 65504/32768 = 1.9990234

+ subtract 1, then multiply by 1024

(1.9990234 - 1) * 1024 = 1023

+ encode significand result into binary

1023 = 0b1111111111

+ bias the exponent (i.e. add 15), then convert to signed two's complement integer binary

15 + 15 = 30 ==> 0b11110

+ concatenate sign, bias exponent, significant

0|11110|11111111111

+ convert to hex

0111 1011 1111 1111 ==> 0x7BFF
GuyPerfect
Catgirl
Level: 68


Posts: 442/1096
EXP: 2665961
For next: 62839

Since: 07-23-07


Since last post: 1.7 years
Last activity: 220 days

Posted on 05-16-08 07:05:31 PM (last edited by GuyPerfect at 05-17-08 03:22 PM) Link | Quote
I was mistaken about denormalized numbers. An exponent field that results in zero when the bias is subtracted actually does indicate 2 ^ 0. According to the standard, the exponent field must be stored as zero (where if you were to subtract the bias you'd get -bias). If the exponent is stored as zero, THEN it's a denormalized number: do not subtract the bias.

My earlier post has been modified to state this.


More from the docs:

Special Values
  • If the exponent is non-zero, the number is normalized and the significand has a leading 1 stuck onto the beginning. This is the normal way to use floating-point numbers.

  • If the exponent is zero and the significand is non-zero, the number is denormalized and the significand does not have a leading 1. The exponent is not used, and the sign is simply applied to the significand. This allows for numbers between 0 and 1.

  • If the exponent is zero and the significand is zero, the number is interperated as zero. This allows for positive zero and negative zero, though that rarely has any meaning.

  • If the exponent is all 1's and the significand is zero, the number represents Infinity. Positive and negative Infinity are allowed.

  • If the exponent is all 1's and the significand is non-zero, the result is Not a Number (NaN).

    • If the most-significant bit of the significand is SET, the number is a Quient NaN (QNaN), which is used to indicate that an operation is undefined. Example: Tan(Pi / 2)

    • If the most-significant bit of the significand is CLEAR, the number is a Signalling NaN (SNaN), which is used to indicate that an operation is invalid. Example: Sqrt(-1)

CellarDweller
Random nobody
Level: 6


Posts: 5/5
EXP: 819
For next: 88

Since: 08-15-07

From: Arkansas

Since last post: 14.0 years
Last activity: 13.2 years

Posted on 05-17-08 06:20:00 AM Link | Quote
The texture coordinates used by N64 games are not floating point. They are fixed point, with 5 bits of fraction. If you want to encode an integer into a texture coordinate, you can just shift it left by 5 bits (ie multiply it by 32).

____________________
Signature way too wide, removed --mgmt.
messiaen
Catgirl
Level: 68


Posts: 92/1085
EXP: 2596623
For next: 132177

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 05-17-08 05:53:14 PM (last edited by messiaen at 05-17-08 03:27 PM) Link | Quote
Thank you SO much, I tested it and indeed this is the format used. Anyway, there is also data stored in floats, so knowledge of these should be useful too.
Next newer thread | Next older thread
Jul - Computers and Technology - Half-Precision Floats to Hexadecimal ? New poll - New thread - New reply


Rusted Logic

Acmlmboard - commit 47be4dc [2021-08-23]
©2000-2022 Acmlm, Xkeeper, Kaito Sinclaire, et al.

31 database queries, 8 query cache hits.
Query execution time: 0.084532 seconds
Script execution time: 0.020207 seconds
Total render time: 0.104739 seconds