ValF("2.3") sometimes returns "2.0"

Just starting out? Need help? Post your questions and find answers here.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

ValF("2.3") sometimes returns "2.0"

Post by c4s »

This is probably the most mysterious error/bug(?) I've ever encountered. Under certain circumstances ValF() seems to return wrong values. Rough example code:

Code: Select all

Global Dim SArray.s(200)
SArray(10) = "2.3"

Global SGlobal.s
SGlobal = ""


Procedure Change()
	SGlobal = "Something"
EndProcedure

Procedure Test()
	Debug SArray(10)  ; Always "2.3"
	Debug ValF(SArray(10))  ; Always "2.0" instead of "2.29..." when SGlobal gets changed
EndProcedure



;Change()
Test()
Unfortunately the code above doesn't reproduce the error but it's approximately how it looks like. All I can say is that the array values never change and that the code above does not run in a thread. Also SGlobal always changes before Test() (as it isn't in a thread)...
I compiled it with PB 4.51 32bit, Unicode and Threadsafe enabled. It produces the error on Windows Vista (Dual Core). However I can't reproduce it on my developing PC (Windows XP, Single Core).

So what I'm asking is: Under which circumstances can ValF() produce wrong results?
Last edited by c4s on Tue Sep 13, 2011 2:17 pm, edited 1 time in total.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Zach
Addict
Addict
Posts: 1677
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: ValF() sometimes returns "2.0" instead of "2.29..."

Post by Zach »

Sideline: I thought Floats were inherently inaccurate ?

I doubt this is a bug - as I found this pretty easily through Google

http://cboard.cprogramming.com/c-progra ... uracy.html
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by c4s »

Yes, they are. However e.g. ValF("2.3") should (and usually does) return "2.29...". However in my case it returns "2.00...".


Edit:
What I forgot to say: I compiled the executable months ago and the error seems to occur since just a few weeks (Windows Update?!).
Last edited by c4s on Tue Sep 13, 2011 2:38 pm, edited 1 time in total.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
jboadas
User
User
Posts: 12
Joined: Thu Jul 14, 2011 7:38 pm

Re: ValF("2.3") sometimes returns "2.0"

Post by jboadas »

In my machine VafF("2.3") returns 2.29999995231628
but ValF("2,3") returns 2.0
check if this have something to do with international configuration of your machine
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by c4s »

Well, the value always has a point (-> ValF("2.3")). But interesting to know that it produces different results. Does it depend on system settings?!

I updated my previous post: The error seems to appear since only a few weeks and as I already said just when the other global string is set. Extremely strange... :|
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
MachineCode
Addict
Addict
Posts: 1482
Joined: Tue Feb 22, 2011 1:16 pm

Re: ValF("2.3") sometimes returns "2.0"

Post by MachineCode »

jboadas wrote:but ValF("2,3") returns 2.0
check if this have something to do with international configuration of your machine
Sounds right. The decimal separator can be . or , depending on your locale. If it's . and you pass a number with , as the separator, then of course ValF() is going to ignore all digits after the , character. Perfectly normal for it to do so.
Microsoft Visual Basic only lasted 7 short years: 1991 to 1998.
PureBasic: Born in 1998 and still going strong to this very day!
DarkDragon
Addict
Addict
Posts: 2346
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: ValF("2.3") sometimes returns "2.0"

Post by DarkDragon »

MachineCode wrote:
jboadas wrote:but ValF("2,3") returns 2.0
check if this have something to do with international configuration of your machine
Sounds right. The decimal separator can be . or , depending on your locale. If it's . and you pass a number with , as the separator, then of course ValF() is going to ignore all digits after the , character. Perfectly normal for it to do so.
It usually doesn't depend on your locale, it is fixed in english notation since the first PB version. Locale handling is much more complex and shouldn't be put in such a simple data type conversion function.
bye,
Daniel
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by c4s »

@MachineCode
Even if this would be the issue, it wouldn't explain why ValF() works perfectly fine when that other string isn't set.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: ValF("2.3") sometimes returns "2.0"

Post by Guimauve »

I have tested the code in LinuxMint 11 x64 witn PureBasic V4.60 RC1 x64 and both test return :
2.3
2.29999995231628
So the problem occur only on Windows, if this can help someone to understand what is really going on.

Best Regards.
Guimauve
citystate
Enthusiast
Enthusiast
Posts: 638
Joined: Sun Feb 12, 2006 10:06 pm

Re: ValF("2.3") sometimes returns "2.0"

Post by citystate »

you say that the code you supplied doesn't reproduce the error?

in the code that DOES, are you accidentally casting to a long or integer?

Code: Select all

a.l=ValF("2.3")
b.i=ValF("2.3")
c.f=ValF("2.3")

Debug ValF("2.3")
Debug a
Debug b
Debug c
there is no sig, only zuul (and the following disclaimer)

WARNING: may be talking out of his hat
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by c4s »

@citystate
No, I'm using something like:

Code: Select all

WriteFloat(FileNr, ValF(GArray(10)))
Where...
- FileNr is a valid, opened file
- GArray(10) is the global array I was talking about in the first post. The value is "2.3"
- ValF() returns "2.29..." and under certain circumstances "2.0"
- WriteFloat() writes "2.0". It's definitely not the problem here.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Little John
Addict
Addict
Posts: 4800
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by Little John »

Without code that reproduces the problem, only some guesswork is possible.

Regards, Little John
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by c4s »

@Little John
Of course. But I was wondering if someone with internal knowledge of PureBasic could tell me what ValF() itself does. Maybe it isn't threadsafe or it interferes with the internal string manager or whatever...
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: ValF("2.3") sometimes returns "2.0"

Post by SFSxOI »

Returns 2.29999995231628 here on Windows 7 Ultimate x86, it is represented within standards requirements correctly. Don't confuse precision with representation.

Part of it is how your CPU does floating point representations, even the compiler may choose different floating point representation methods. From what I discovered about C++ (in which I am certainly no expert), the rest I think is explained by how windows stores the mantissa. The mantissa is stored as a binary fraction and has a value greater than or equal to 1 but less than 2. Because this bit is always 1, it is assumed in either the real*4 (8 bit) and real*8 (11 bit) formats which have biases of 127 and 1023 . The binary (not decimal) point is assumed to be just to the right of the leading 1, and PureBasic is also the same way (I think) and the help alludes to this (a little bit) where it says "Another limitation of floating point numbers is that they still work in binary, so they can only store numbers exactly which can be made up of multiples and divisions of 2." . Most compilers have options that let you indicate how you want to work with floating point operations, generally faster is less accurate and more accurate is slower. It will behave differently on different operating systems, its one of the inherent "flaws" in using floating point numbers in that there is no gurantee it will behave the same all the time, I try to stay away from working with them myself unless I am using multiples of 2 and then I generally round. If you need more accuracy, consider doubles instead of floats. Plus your number (2.3) is not a multiple of 2, numbers that are a multiple of 2 are more accurate for floats, for example:

Code: Select all

Debug ValF("2.4") = 2.40000009536743
and
Debug ValF("2.3") = 2.29999995231628

you can see the difference between one which is a multiple of 2 (the 2.4) and the other which is not a multiple of 2 (the 2.3)

The Purebasic help says this:

"Special information about Floats and Doubles

A floating point number is stored in a way that makes the binary point "float" around the number, so that it is possible to store very large numbers or very small numbers. However, you cannot store very large numbers with very high accuracy (big and small numbers at the same time, so to speak).

Another limitation of floating point numbers is that they still work in binary, so they can only store numbers exactly which can be made up of multiples and divisions of 2. This is especially important to realise when you try to print a floating point number in a human readable form (or when performing operations on that float) - storing numbers like 0.5 or 0.125 is easy because they are divisions of 2. Storing numbers such as 0.11 are more difficult and may be stored as a number such as 0.10999999. You can try to display to only a limited range of digits, but do not be surprised if the number displays different from what you would expect!

This applies to floating point numbers in general, not just those in PureBasic.

Like the name says the doubles have double-precision (64 bit) compared to the single-precision of the floats (32 bit). So if you need more accurate results with floating point numbers use doubles instead of floats.

The exact range of values, which can be used with floats and doubles to get correct results from arithmetic operations, looks as follows:
Float: +- 1.175494e-38 till +- 3.402823e+38
Double: +- 2.2250738585072013e-308 till +- 1.7976931348623157e+308"

If you take a look at the IEEE standard at http://en.wikipedia.org/wiki/IEEE_754 you will find that the representation your seeing meets the standard requirements, so although it may not be as precise as you wish the representation is correct according to the standard.
Last edited by SFSxOI on Wed Sep 14, 2011 7:59 pm, edited 2 times in total.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ValF("2.3") sometimes returns "2.0"

Post by c4s »

@SFSxOI
Thanks for this detailed information about floats but I think you didn't realize that I'm not talking about very small differences like 0.0001.
I didn't test it yet (as I can't reproduce it on my developing computer) but I think everything after the point gets truncated in the ValF() function under certain conditions. It really doesn't make any sense! Again something simple to illustrate my problem:

Code: Select all

Debug ValF("2.3")  ; Returns 2.29999995231628

; Do some simple stuff such as changing strings etc. (see first post)
Debug ValF("2.3")  ; Returns 2.0
Tomorrow I'll hopefully be able to test a little more and be able to give some real reproducible code.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Post Reply