How to output a Floating Point number ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

How to output a Floating Point number ?

Post by White-spirit »

Hello ,

How to output a Floating Point number on the screen if the precision is unknown ?

I wrote a fasm code to do that but it displays for example 28.0710391998291015625 instead of 28.07104 :?

Here's my code ( will be optimized after :

Code: Select all

format elf

public ftol
public print_float
extrn print
extrn putchar
extrn itoa

half dd 0.5
i dd ?
tmp dd ?
e dd ?

ftol:
fld [half]
fld dword [esp+4]
fsub st0, st1
fld dword [esp+4]
faddp st2, st0
fistp [i]
mov eax, [i]
fistp [i]
add eax, [i]
sar eax, 1
ret

print_float2:
push ebp
mov ebp, esp
mov ebx, dword [esp+8]
mov [tmp], ebx
push [tmp]
call ftol
add esp, 4
mov [e], eax
push 0
push 0
push 10
push [e]
call itoa
add esp, 16
push eax
call print
add esp, 4
push '.'
call putchar
add esp, 4
fld [tmp]
fisub [e]
fst [tmp]
.do:
push 10
fimul dword [esp]
fst [tmp]
push [tmp]
call ftol
add esp, 4
mov [e], eax
push 0
push 0
push 10
push [e]
call itoa
add esp, 16
push eax
call print
add esp, 4
fisub [e]
fst [tmp]
ftst
fstsw ax
fwait
sahf
jnz .do
leave
ret
Where's the problem please ?

PS : itoa, print, and putchar are my own written functions, so they aren't standard .

Thanks :)

Thanks .
Last edited by White-spirit on Thu Dec 01, 2011 5:47 am, edited 1 time in total.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Hi,

Floating point errors are extremely common, you'll have to get used to them. Remember that in pure mathematical theory one cannot ever test for equality of two items of a continuous set. Some delta, or leeway value must be applied.

i.e. x == y iff x-delta < y < x+delta.

PS: Code comments are nice things.

Cheers,

James
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Okay thanks, so there are no errors on the code instead of the floating point comparison ?

PS : it's hard for me to put comments on the code ( non-native English speaker ), but i'ill try :)
arkady
Posts: 17
Joined: Wed Jan 02, 2008 3:14 pm
Location: Poland

Post by arkady »

JamesM is right about floating-point numbers. My tip for you, White-spirit is to change precision to 64 bits (long real?). "32-bits real numbers" (dd) have only 23 bits for mantissa so your 28.07104 is actually presented as:

(1+6328701/2^23)*2^4

which equals exactly 28,0710391998291015625. Precision.... And maybe try to avoid showing too many digits. 10 should be good for most purposes-with "long real FP numbers" it should be precise enough.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

the amount of digits is limited to the actual precision - i.e. the maximum amount of digits you need to print to identify one specific float can be computed:
10log(2^(mantissa+1)) + 1
you can just count away the printed digits, and when you have enough digits, or you have a zero remainder, you can stop.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

Most hardware and software floating point methods only guarantee a specific number of digits of accuracy. Traditionally (since the '60s) a 4 byte floating point calculation is only guaranteed to be accurate to 7 digits -- that is, the sin() function's output will be wrong past the 7th digit, for example. An 8 byte float is guaranteed to 15 digits. You might want to consider these values to be your output maximums, on top of Combuster's method for stopping when the remainder goes to zero (or gets "close enough" to zero).
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

So it's not possible to print a floating point number without giving a specific precision ? :(
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

Remember (or check out) how floating points are actually represented by the CPU. Even something as simple as "0.1" cannot be represented exactly. There is no way to get the "original" values back once they have been through a CPU's registers, except by rounding, and to round you have to state a precision...

Check out DBL_DIG and FLT_DIG in <float.h>.

Also remember that a float can be NaN (not a number), or Infinity, both of which are special bit patterns of a float your output code should be able to detect.

There is a reason why I haven't implemented floats in PDCLib yet. ;-)
Every good solution is obvious once you've found it.
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Okay thanks, actually I'ill print the floating point number in 10 digits ( it still doesn't look good because it can contain many digits :s ) , but I'ill not give up on searching a way to display a floating point number without specifying a precision :mrgreen:
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

Still tackling the problem from the wrong end. The output of "28.0710391998291015625" is absolutely correct. Your initial value of "28.07104" was lost the moment you squeezed it into a FPU register.

If you want precise handling of such numbers, you have to implement a library that represents those numbers without using the FPU. More precision, less performance.
Every good solution is obvious once you've found it.
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Okay thanks, I added a ".Xf" support to my printf function so I don't have to worry about that :P .
Post Reply