Android Question Float too dirty

Saverio

Member
Licensed User
Longtime User
The Code is this:
B4X:
Dim S As String
Dim F As Float = 5.55
S=F
Log(S)
Log(F)

The problem is that I will get a very long float at log, something like 5.550000190734863

But, what is more strange is that: if you pause the app and watch debug frame you will see
the "F" variable correct and the "S" variable come with wrong long number.

I've tried that either on a real phone and emulator. Got same result

The question is:
Do Someone of you know somenting about this?

img10.jpg

Thank you
Saverio
 

Saverio

Member
Licensed User
Longtime User
Hello thedesolatesoul nice to meet you.

I surfed the forum but miss that.

I think there are two problem.
One - is what, in your link, they are talking about.
Two - I could think, Ok this is the fact, what can I do?

I did this:

B4X:
Private Sub CutDec(num As Float, DecCount As Int) As Float
    Dim dec As Int
    Dim intPart As Int = num
    If DecCount < 1 Then Return(intPart)
    Dim decPart As Float = num - intPart
    dec = decPart * Power(10,DecCount)
    Return(intPart + (dec / Power(10,DecCount)))
End Sub

Now, what appen is that if I use the Log to control the variables, what I will get is wrong.
But, as I said in the above, if I control them by debug, the variables that I read are absolutely correct.
Exactly as in the attached picture

So the more specific question is:
Why, Debug show me the correct result, where Log don't?

Ha!, anyway, it will "fail" also if you try convert Float to String.

Thank you
Saverio
 
Upvote 0

Saverio

Member
Licensed User
Longtime User
I've tried that, don't work and, even when, it would be to slow.
(but I think this drive us in another discourse)
.
.
.
.
I'm gettin' crazy! o_O:eek:
Loock at this:

img11.jpg

If I use a Float variable or a custom type float variable, I will get wrong.
But if you put Log(myType) you will read the correct result in the right panel:

B4X:
Sub Globals
    Type myType(F As Float, G As Float)  
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim S As String
    Dim F As Float = 5.55
    S=F
    Log(S)
    Log(F)
    ' Until here it's not working
    ' Now look at this
    Dim mt As myType
    mt.F = F
    Log(mt.F)
    Log(mt.G)
    Log(mt) 'so this is working?
  
    S=S 
  
End Sub

It's just to know.
 
Upvote 0

Saverio

Member
Licensed User
Longtime User
I don't want convert numbers to strings.

I whish to know why Log(mt.F) get "dirty" value and, instead, Log(mt) read the values, corectly?
 
Upvote 0

James Chamblin

Active Member
Licensed User
Longtime User
After a bit of testing, I figured it out. First, as thedesolatesoul has pointed out, a float can't be represented perfectly in binary. An example would be to represent 1/3 in decimal. .3333333 is not quite it, add more 3s and you still wont get exactly 1/3. Keep adding 3s and you will get a number closer to 1/3, but never exactly 1/3. Same thing happens when converting a number to binary. 5.55 cannot be represented exactly. You can get closer by using a double instead of a float, but you will still be off a certain amount.

Now as to why Log(S) prints 5.550000190734863 and Log(F) prints 5.55 has to do with the precision when converting to a string. When you cast F to a string, it will convert to 16 characters, and Log(S) prints out the entire string. When you pass F to Log(), it gets cast to string within the Log() function, but it is only doing 8 characters, then printing out. So Log(F) is really printing "5.550000" with the trailing 0s removed. To test this, try using 1.234567890123456789 instead of 5.55

BTW, if you ever need to test 2 floats for equality, it is better to test for difference, and if it is within a certain threshold, consider them equal
If Abs(F1-F2) < .0001 Then TheyAreEqual()
 
Upvote 0

Saverio

Member
Licensed User
Longtime User
mmm... I understand that my English is not so good.
But I'll try again. Sorry guys but I don't understand so easily.:D

OK I agree with all of you. It's not so easy represent a float or a double in bynary.
And, what is for sure is that: I don't want convert Nothing!

I want know what there is behind Log function.

The Code is this:
B4X:
Sub Globals
    Type myType(F As Float) 
End Sub

Sub Activity_Create(FirstTime As Boolean)

    Dim m As myType
    m.F = 5.55    
    Log(m.F) ' here the result is: 5.550000190734863
    Log(m)   ' here the result is: [IsInitialized=false, F=5.55]

End Sub

From where, Log function, take out the F=5.55 ?
 
Upvote 0

Saverio

Member
Licensed User
Longtime User
Ok! As you want.
Usually I'm a lazy boy.
But not today. :D

I don't want convert numbers to strings.

I know that calling Log, numbers are converted to strings(otherwise what?)
And, of course, the same happen with Labels text and with any other kind of text Views.

I just want to know what I'm doing.

I did my homework.
I thought, before I start open my mouth again, at least, I have to get some knoledge.
java.lang.Float
android Float
Wiki Float

I have tried:
(For Windows)
Visual Basic 6, 2010, 2013 (Dim f As Single)
Visual C++ 6, 2010
Visual C# 2010
Eclipse for Java (latest version)

(For Android)
Eclipse + ADT (latest version)

All of them returns what I did expect from them.
Take a look at the attached picture. It will show either Double and Float limits.
But, even so, numbers remain clear. There isn't "over-numbers".
Eclipse.png

So, now, the question is:

In B4A, for Float type, are you wrapping the java.lang.Float class, or are you using your own class?

Regards
Saverio
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
E' la "funzione" Log che converte tutto in stringa, ma solo per la visualizzazione; non converte le variabili del progetto.

Nel tuo primo post, tu vuoi che S (string) contenga pochi decimali, quindi probabilmente ti serve solo per la visualizzazione, mentre per i calcoli devi continuare ad usare le variabili Float e Double, per la visualizzazione (o per l'assegnazione ad una variabile stringa) devi usare la funzione NumberFormat.

(There is an italian forum, on this site ;))
 
Upvote 0

Saverio

Member
Licensed User
Longtime User
@Erel!

I know, in declaration, is float, I have capitalized it just to spot it.
Anyway the class's static name is java.lang.Float. :D

I've used Log() just to show what happen. I don't know other way.

So in the end if we have a variable v, declared as float, with value of 5.55 and we do v*v,
the result inside v, will be correct, right?.
What will be wrong it will be the string representation of a number, unless using FormatNumber.

But, I don't want convert numbers to strings.

I'm simply talking about very big numbers, cosmological distance, light-years, parsec and so on, where every decimal counts. This is just an example, there are other reasons where every decimal counts.
Think about trigonometric functions, but I don't want debate about them, here.
Ok, someone might think this is science-fiction, but anyway that's are the facts.

I'm not a programmer, but, what I know for sure is that I want to know, where possible, the system limits,
either toward the devices that toward B4A, to avoid, writing lot of code, and, at the end, rewrite everything,
just for a bit. Hope I was clear.

So, as suggested by agraham in the link posted by thedesolatesoul(post #2),
it would be better to use Long or BigInteger for float and double numbers.

Erel, I really like Basic4Android. It's a very nice tool, over all, the IDE.
But I'm also saying, if you push it a little forward, to make it even more useful, I think, it's not a bad idea.
What do you think about it?

@LucaMs,
I don't have nothing against Italians.o_O
But I would prefer to remain in this forum, at least from sharing point of view.
Or are you thinking I have a low English skill?:cool:
savesse@tiscali.it
savesse@gmail.com

Thanks to all of you
Regards

Saverio
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
"Or are you thinking I have a low English skill?"

Google Translate has a low Italian skill and I use it, trying to correct its translations :D
(in fact, I did not understand what does the IDE with the topic of the thread).

I should re-read everything, but I'm lazy.

To me, everything is resolved with:
variables have limitations, I suppose that these limits are specific to Java/Android, not to B4A.

For precise calculations, we must use Double, NumberFormat for displaying. Eventually, we could use the rounding functions.

Di sicuro in italiano ci capiremmo meglio, almeno io capirei meglio :D
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
So in the end if we have a variable v, declared as float, with value of 5.55 and we do v*v,
the result inside v, will be correct, right?.
5.55 cannot be represented exactly in base 2 (binary). So there will always be a very small inaccuracy. The result will be exactly like the result you get if you write similar code in Java, C, C# or any other language.

What will be wrong it will be the string representation of a number, unless using FormatNumber.
No. The number is not wrong. It is just rounded.

But I'm also saying, if you push it a little forward, to make it even more useful, I think, it's not a bad idea.
What do you think about it?
This is actually a bad idea. In 99.99% of the cases float or double accuracy is good enough. For the other 0.01% the developer can use the BigNumbers library instead.

Note that this is exactly the same situation as in Java (and other languages).
 
Upvote 0

Saverio

Member
Licensed User
Longtime User
5.55 cannot be represented exactly in base 2 (binary). So there will always be a very small inaccuracy. The result will be exactly like the result you get if you write similar code in Java, C, C# or any other language.

Please,
read carefully post #5, post #7 and post #9.

Log(m.F) return 5.550000190734863 (inaccuracy)
Log(m) return F=5.55 (where is the inaccuracy?)
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Please,
read carefully post #5, post #7 and post #9.

Log(m.F) return 5.550000190734863 (inaccuracy)
Log(m) return F=5.55 (where is the inaccuracy?)
"Log" converts the parameter to a string before logging it.

EDIT: The problem is that the conversion is not straightforward (Float.toString(F)). Your float is converted to a double and the double is converted to a string (you can see that in the generated source code of your app).
So you're right, the problem lies in the B4A code. The question is: is this problem limited to the log function?
 
Last edited:
Upvote 0
Top