Jump to content

floating point conversions


Recommended Posts

I have the need to build my own caculator for converting a floating point to a hexadecimal.

Here is a site that does it for you

http://babbage.cs.qc.edu/IEEE-754/Decimal.html

This value I need is used for a Dword registry value. As an example, if I input into that webpage the value of "1", the result I need will be "3F800000". If I enter a fractional number, such as "3.4", the result will be "40599999".

I have messed around with the inbuilt functions but don't seem to get the results the same way. I have experimented with Ptrex and Jennicos versions of HexDec converters, but again, don't seem to find the correct conversions. I have examined some rather complicated documents online, and see what amounts to more than I currently understand to do (regarding mantissa, etc).

Is there a UDF anyone knows about that does this already, or does anyone have any advice on how I can achieve the conversion. I need to only be able to take a number, either whole (ie. 1 or 5) or fractional (ie. 1.5 or 5.2) and have the result be available as both rounded and non-rounded.

Maybe I need to do bit work in here, but don't understand exactly why the hex value I need is different from using a Hex() func.

Sul.

Link to comment
Share on other sites

lol, did you know the answer?

It took me some time, but after opening a dozen different web pages concerning floating point binary (signed 32) calculations, I finally got the point of how to convert to binary, find the exponent and mantissa, how they structure and shift it, which finally leads to being able to convert to hex the final binary notation. Quite complicated really :)

Tommorrow I will create some code for it if I haven't forgot it, and post it back here for other inquisitive souls.

BTW, that link you provided is a great one, but it took a lot of other "basic" info before I was able to put the pieces it was showing me together.

Sul.

Link to comment
Share on other sites

Or it seems you could also use this

_WinAPI_FloatToInt($float)

but wouldn't that be too easy lol?

Sul.

Interesting. I've never stumbled across that particular function before!

Either I'm getting too old for AutoIt, or AutoIt is getting too big for me.

:)

Edit: And no, Melba23, my dog did not eat my help file!

;)

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

I apologize before-hand for improper references and terms. This is just a hobby for me, no formal schooling on the topics :)

While I don't need to write the code now, as the API call works fine, I will share what I found for others who might be looking for

floating point binary hexadecimal

or properly

Single precision floating-point format

or just

IEEE 754-1985

I found infos at the link you provided PsaltyDS and also here

http://en.wikipedia.org/wiki/Single_precision_floating-point_format

and a good read at these forums here

Using the example from wikipedia, it breaks down like this for the beginner

A single precision floating point uses 32 bits, broken down like into 3 parts: the sign, the exponent and the mantissa/significand

The sign is the left most bit and is 1 bit long. A value of 0 indicates a positive and 1 indicates negative.

The exponent is 8 bits long and is used strangely for someone who has never done this before.

The mantissa/significand is 23 bits long and while strange, is pretty easy to get. The precision of the conversion is limited to these 23 bits.

Lets take a number like wikipedia uses

12.375

First break the whole from the fraction

12 is the whole and .375 is the fraction

The goal is to get a binary32 value from these and then convert that to hex.

We first break 12 into binary.

Remember binary is 4 bits with the values from left to right 8,4,2,1.

Larger numbers require 8 bits with values from left to right 128,64,32,16 8,4,2,1

So 12 fits into the first 4 bits easily, using the 8 and 4 and ignoring the 2 and 1, like this 1100.

For the fractal, you multiply by 2, until the result is even. If the result has a fractal, then you multiply that fractal by 2 until you either see a repeating pattern or you get a whole number result. Remember that this binary representation of the fraction part of the number is going into the mantissa/significan, so you only have 23 bits to work with.

The fraction is .375

.375 x 2 = 0.750

There is no whole number, so the first piece of the binary conversion is 0

The result is not whole, but still a fraction, so we take the fraction and repeat.

.750 x 2 = 1.50

There is a whole number in the return value, so the second piece of the binary conversion is 1

The result is still not whole, sw we take the fraction and repeat.

It might be helpful to imagine that we take the whole number of the return value, whether a 0 or a 1, and remove it, placing it in the binary conversion, therefore we never carry over a whole to the repeated sequence.

.50 x 2 = 1.00

Here we have another whole number, so the next piece of the binary conversion would be 1

Here we also see that we have finally produced a whole number with no fraction left over, so we end our conversion.

It might be that the multiplication sequence starts to repeat itself into a pattern over and over. When we see this, we can simply fill that pattern out to 23 binary digits if we want to stop.

So lets give 2 examples. The first example, as described above, is done. We end up with a 0, a 1 and a 1. This is binary, so it is 011. Since our .375 ended up with an even return, we only have to use 3 binary digits.

But, suppose your fractal number was .3

.3 x 2 = .6 -> a binary 0 and repeat

.6 x 2 = 1.2 -> a binary 1 and repeat

.2 x 2 = .4 -> a binary 0 and repeat

.4 x 2 = .8 -> a binary 0 and repeat

.8 x 2 = 1.6 -> a binary 1 and repeat

.6 x 2 = 1.2 -> a binary 1 and repeat

.2 x 2 = .4 -> a binary 0 and repeat

.4 x 2 = .8 -> a binary 0 and repeat

.8 x 2 = 1.6 -> a binary 1 and repeat

.6 x 2 = 1.2 -> a binary 1 and repeat

You can see how the pattern is going to be never ending. Since we know the mantissa/significand only holds 23 binary digits, we can just fill it out with the patter, like this

01001100110011001100110

Back to our example using 12.375 then.

Our first conversion resulted in

12 = 1100

and

.375 = 011

we put them together keeping the decimal point like this

1100.011

Here is where it gets interesting. There is a piece of the binary32 data format called the exponent, it is 8 binary digits long. But now we use another exponent as well. You must remember to know which exponent you are referring to!

The first thing that has to be done is to get our 1100.011 into I believe what is called a "biased" format. All you do is shift the decimal place to the left in our case until you have a 1 on the left of the decimal. Only a 1 may exist there. We must shift 3 places.

1100.011 = 1.100011

The number of places we shifted the decimal is now our "exponent". We are done with the mantissa/significand. For all purposes, we are going to forget the leading 1 and decimal, and only save what remains

so 1.100011 is really going to be used as 100011 later.

Next we need to take our "exponent" that represents how many places we moved our decimal, and build the "exponent" portion of the binary32 form. It is strange, but you essentially take the "decimal exponent" and add it to the value 127. So 127 + 3 = 130.

Now you must create that value, 130, in an 8 bit binary format. Remember those 8 bits, from left to right, are

128 64 32 16 8 4 2 1

to make 130, it would be

1 0 0 0 0 0 1 0 or 10000010

finally, we must have a sign, which is the left most bit of the binary32 form. Since this is a positive value, the sign will be 0.

To look at the whole binary32 form of the value 12.375 then, it looks like this

0-10000010-100011

Noting that the sign is positive, so the first binary digit is 0

Noting the exponent = 130 so it is 10000010

Noting the mantissa/significand we calculated as 1.100011, but we dismiss the decimal and the 1, so 100011

Bearing our end structure, without the hyphens to distinguish the 3 different components of the binary32 format

010000010100011

Now we can make a hexadecimal conversion. Split this form into 4's

0100 0001 0100 0110

You may notice that the end value 0110 I padded with a 0. Because a hex value will have 8 digits, you simply pad it with 0s, like this actaully.

0100 0001 0100 0110 0000 0000 0000 0000

and convert to hex

; DECIMAL 0    1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16
; HEX     0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F    10
; BINARY 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111  10000

0100 0001 0100 0110 0000 0000 0000 0000

4 1 4 6 0 0 0 0

or

0x41460000

I needed a registry value in this format, rather than the usual Hex() return value. I don't plan on creating code for it since I don't want to reinvent the wheel and there is a nice function already available. But, I did want to learn why, and hopefully someone else one day will stumble upon this in a web search and can benefit from it.

Sul.

Link to comment
Share on other sites

  • 5 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...