writefloat calc question

Just starting out? Need help? Post your questions and find answers here.
Fable Fox
User
User
Posts: 29
Joined: Fri Dec 12, 2003 4:52 am

writefloat calc question

Post by Fable Fox »

i need to know something not important, but intriguing:

writefloat(5) and writefloat(6) is written as 00 00 a0 40 and 00 00 c0 40 (in the file, read using hex editor)? can someone explain it to me? this is because everything else byte, word, etc get written as their hex equivalent?, for example 10 = 0A. Does someone know how computer calculated that it arrive at 0000a040 and 0000c040?

does someone who good at comp math explain how you store point value, such as 3.5 or 5.8 in hex? thanks.
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

Big question, that.

Floats are stored using a standard called IEEE-754. This approximates the value, which is why floats are not always absolutely 100% accurate.

Floats have a sign bit, an exponent, and a mantissa (and some implied values) and these are used together to calculate the value.

This code (more or less shows) how a 32 float is handled.

Code: Select all

Structure single_TYPE
  StructureUnion
    flt.f
    int.l
    cha.b[4]
  EndStructureUnion
EndStructure

sng.single_TYPE

Procedure.s zLeft(valu,dgt)
  ProcedureReturn Right("00000000000000000000000000000000000000000000000000000000000000000"+Bin(valu),dgt)
EndProcedure

; Format of a 32 bit IEEE-754 float;
; Bits: Seeeeeee eMMMMMMM MMMMMMMM MMMMMMMM
; Where S = Sign
;       e = exponent
;       M = Mantissa (or fraction or significand, your call)

Procedure calcIEEEsingle(vlu.f)
  
  Debug ""
  Debug "-------------------"
  Debug "ORIGINAL = " + StrF(vlu)
  Debug ""
  
  ;Stick the original value into our structure
  sng.single_TYPE\flt=vlu
  
  ; Because of endian-ness, use reverse order
  ;  in processing the 4 bytes

  signIs=(sng\cha[3] & $80) >> 7
  If signIs
    signIs=-1
    Debug "Value is NEGATIVE"
  Else
    signIs=1
    Debug "Value is POSITIVE"
  EndIf
  
  ;Next 8 bits are the exponent.
  ; Need to give them a little shift to the left
  exponent=((sng\cha[3] & $7F) << 1) + ((sng\cha[2] & $80) >> 7)
  Debug "Raw exponent = "+Bin(exponent)
  
  ;Mantissa is next 23 bits (base 2)
  ; Do some shuffle, using several code lines for readability.
  mantissa=(sng\cha[2] & $7F) : mantissa << 8
  mantissa+(sng\cha[1] & $FF) : mantissa << 8
  mantissa+(sng\cha[0] & $FF) : mantissa * 2
  
  Debug "Raw Mantissa = "+zLeft(mantissa,24)+" ("+Str(mantissa)+")"
  Debug "This is ..."
  If exponent=255 And mantissa<>0
    Debug "... NaN"
  ElseIf exponent=255 And mantissa=0
    If signIs=-1
      Debug "... Negative Infinity"
    Else
      Debug "... Infinity"
    EndIf
  ElseIf exponent=0 And mantissa=0
    If signIs=-1
      Debug "... Negative zero (-0)"
    Else
      Debug "... Zero"
    EndIf
  ElseIf exponent=0 And mantissa<>0
    Debug "... a Denormalised number"
  Else
    Debug "... a Normalised number"
    
    ; Calculate the mantissa as a "binary decimal"
    man.f=1.0                    ; There is an invisible or implied one
    flag=$00800000               ; This flag used to check the bits
    adj.f=1.0                    ; This value halved for each bit
    
    For i=1 To 23                ; Check each bit for mantissa bits
      adj / 2.0                  ;   Halve our value
      If mantissa & flag         ;   If the bit is set
        man + adj                ;     add value to mantissa
      EndIf                      ;
      flag >> 1                  ; Shift the bit one place right
    Next                         ;
    
    ; Test the result:
    ;    Note -  exponent here adjusted by -127 (the "bias")
    ;    However, this should be checked earlier as it can
    ;             change this, for example whether the
    ;            "decimal binary" starts with 1. or 0.
    ; But who cares!

    ; Make everything a float.
    ; Not absolutely needed, but ...
    fSign.f = signIs
    fExp.f = exponent
    
    IEEE754val.f= fSign * Pow(2.0,(fExp-127.0)) * man
    Debug StrF(IEEE754val) + " is the IEEE-754 value"
    Debug StrF(vlu) + " is the original value."
  EndIf
EndProcedure

odds.single_TYPE

odds\int=$0        : calcIEEEsingle(odds\flt)
odds\int=$80000000 : calcIEEEsingle(odds\flt)
odds\int=$7F800000 : calcIEEEsingle(odds\flt)
odds\int=$FF800000 : calcIEEEsingle(odds\flt)
odds\int=$80       : calcIEEEsingle(odds\flt)

calcIEEEsingle(1.0)
calcIEEEsingle(-1.0)
calcIEEEsingle(123.45)
calcIEEEsingle(-123.45)
calcIEEEsingle(0.1)
calcIEEEsingle(-0.1)
calcIEEEsingle(1.0/3.0)
calcIEEEsingle(22.0/7.0)
calcIEEEsingle(123.456)
calcIEEEsingle(123.4567)
The above is for a single precision float. These are reasonably accurately represented up to about 7 digits.

A double precision float (64 bits) pushes it around 15 digits, when the wheels start to wobble badly again.

Note that the exponent determines things like 0, -0 (which it appears PureBasic kindly sorts out for us, saving us some heartache), NaN (not a number) and Infinity.

Note also that the reason it is stored back to front (hex 00 00 a0 40 and not 40 0a 00 00) is nothing to do with the float and everything to do with the endian-ness of the computer.


lol. Having just typed all that, I hope that was what you were looking for. :)
@}--`--,-- A rose by any other name ..
Hatonastick
Enthusiast
Enthusiast
Posts: 149
Joined: Wed Apr 27, 2005 11:50 am
Location: Adelaide, Australia
Contact:

Post by Hatonastick »

Yeah and this is a bit of a gotcha to those who don't know this - as Dare2 showed me a day or so ago. :)
Please forgive my poor English, I'm an Australian.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

i've discovered that too....

I guess they are called floats for a reason, cause they are kinda - almost - but not really :)
MrMat
Enthusiast
Enthusiast
Posts: 762
Joined: Sun Sep 05, 2004 6:27 am
Location: England

Post by MrMat »

Nice explanation Dare2 :)
Mat
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

Thanks MrMat! :)

I must have had one brain cell actually in synch with another when I wrote that.
@}--`--,-- A rose by any other name ..
Fable Fox
User
User
Posts: 29
Joined: Fri Dec 12, 2003 4:52 am

thanks.

Post by Fable Fox »

wow - nice explanation. i do know about that backward thing. i'm an experienced (dos days) save game hacker. it just that i never learn hex past that mantissa thing.

thank you very much.
Post Reply