Multiplication problem Single/Integer

Why the multiplication of 3.6 by 20 = 71 (instead of 72)
when 3.6 is Single and 20 is Integer?

Round () solved this case but this intrigues me.

<https://xojo.com/issue/47066>

This produces the correct result (simply changed results to double):

[code] Dim result1, result2 as double
Dim V as Single= CDbl(TextField1.text)

	result1= V*20
	result2= Round(V*20)
	
	Label1.Text="* 20 = "+str(result1)+" —— With Round() = "+str(result2)[/code]

Forcing result to integer in practice truncates it.

But that integer receive 72 to show… (not 71.123456)…

[code] Dim aSingle As Single
Dim aInteger As Single // was: Integer

aSingle = 3.6

aInteger = aSingle * 20[/code]

aInteger holds “72,” in my computer, in the debugger (that means 72.)…

The error is internally in the way Xojo do the operation.

It is not a bug, it is the way computers work.

The problem is that 3,6 is 2 + 1 + 0.5 + 0.1

While you can express 2, 1, and 0.5 precisely in binary (2^1, 2^0, 2^-1) you cannot do it for 0.1.

So 0.1 and therefore 3,6 can only be approximated (like 3.6000000001 or maybe 3.59999999999)

The multiplication with an integer gives the correct result (Xojo rounds it internally), however putting that result into an integer results in truncation as Michel pointed out.

Take home message: doing maths with mixed types is a recipe for disaster.

I will use Round().
Thank you for your help and clarification.

aSingle = 3.6

In the debugger aSingle = 3.6000000001 (I do not recall the number of zeroes).

That said:
a. It seems strange at first,
b. If it were me, I set 3.6 to a Single variable after I see the discrepency.

Fortunately many work arounds exists.

So you prefer to use round which in fact produces an inexact result, over simply using double for result ?

Mon Dieu …

I’m with Michel: Doing non-integer maths with integers boggles the mind …

Sorry but after further testing I do not see how “Round” gives an inexact result.

I agree with your solution “double” vs “integer” but I still have to truncate (with round or other) : i need an “integer” result afterwards.

Thank you for your patience!

If you NEED an integer result then of course you should use Round at the end. Or Floor, depending on your needs.

However this is the first time that you said you NEED an integer result. Don’t you think you should have mentioned that?

[this is the point where I want to throttle someone. Think Homer & Bart]

In my example:
Dim result1, result2 as INTEGER

So of course I wait for an integer…

This is no reason to upset Homer :wink:

[quote=317174:@Benoit Griveau]In my example:
Dim result1, result2 as INTEGER

So of course I wait for an integer…

This is no reason to upset Homer ;)[/quote]
In Markus’ defense… the code in you last post never appeared previously in this topic

What you don’t get, Benoit, is that forcing the result into an integer is precisely what creates the wrong result. Using round to correct that is computing la Shaddock : I compute wrong, and then I use round to make it right. That is no way to code.

Look at the code I posted. It is exactly your code, with only one difference : instead of cramming the result into an integer which truncates the value into 71, I simply put the result into a double, and it is correct.

Mathematics are an exact science. You don’t accommodate approximately. You think you found a solution because in you very limited example, round seems to produce the correct result. Sure, with 3.6 or even 3.65 it seems to do. But what is the first term is 3.69 ? Then the exact result is 73.8, not 74.

You are free to code wrong, of course. But then don’t file bug reports for bugs you created yourself.

More importantly: just because you USE integer does not mean you NEED integer.

You assume that we can read your mind. We can not.

Now come closer. Closer. Clo … CHRCHRCHR :stuck_out_tongue_winking_eye:

Michel,I think what YOU are missing is the INTENT of the OP…
what you are saying is “right” and “wrong” is from your perspective, not from his.
If what the OP is doing was considered to be WRONG in all situations, then we would have no need for ROUND, CEIL or FLOOR would we? (playing devils advocate here)

There are a lot of situations where I backstore data as double, but when it goes to the presentation layer, I only need a “close” value that must be Integer…

Another thing to consider… Xojo is not strict with its datatyping, but there are other languages that are…and in those languages you would not even be ALLOWED to do “dbl” times “integer”… so in those cases what is “right”?

  • INTEGER(dbl) times INTEGER
  • INTEGER(dbl times DOUBLE(INTEGER))

Even if the end result should be an integer, that is no reason to keep code that produces wrong results, and then crutch it up with round. That is even less reason to blame Xojo for a bug that does not exist. Casting a double to an integer is not done with the equal sign, but precisely with round, ceil or floor.

I would suggest first performing the calculus properly and if he wants an integer as end result, use round from the right result.

Something like

[code]Dim result1, result2 as double
Dim ResultInt as Integer
Dim V as Single= 3.6

	result1= V*20

ResultInt = Round(result1)[/code]

To make it more compact, something like this would work too :

resultInt= round(V*20)

I guess my point is you cannot build proper code based on wrong results. But well, it is not my code…

Sincerely I thank you for your contributions, although I do not understand why some answers are a bit aggressive or preemptory.
No doubt I will speak better in French.

I wrote in my first message:
Round () solved this case but this intrigues me.

I had created a project in the Feedback, I should have pasted the code here, ok.

There are cases where an Integer could receive the result of a Single multiplied by another Integer.

Another example that may be more explicit:

[code]	//Another example
	
	Dim size as Single= 3.6//dimension (cm)
	
	Dim nPixelsRound as Integer
	Dim nPixels as Integer
	
	//Round for closest integer value
	nPixelsRound= Round(size*10)//scaling
	//-> we obtain 36 pixels (integer)
	
	//
	nPixels= size*10//scaling
	//-> we obtain 35 pixels
	
	MsgBox "3.6 cm * 20 = "+str(nPixelsRound)+" pixels (with Round)"+EndOfLine+_
	"But 3.6 cm * 20 = "+str(nPixels)+" pixels (without Round)"+EndOfLine+EndOfLine+_
	"I was only intrigued by this result."+EndOfLine+_
	"Round is a correct solution here."[/code]

Of course Round (or Ceil or Floor) is required here.
But maybe other people less competent than you (like me) can also find this bizarre result:
3.6 (single) * 10 (integer) = 35 (integer).
Especially since the compiler does not prohibit this.
One would expect more logically: 36.

But the explanation of Markus is logical (from the computer point of view).

Since you think the language barrier prevents you from exchanging correctly, here my point in French :

Benoit, nous avons tous tent de vous faire comprendre pourquoi lorsque vous attendez que

3.6 (single) * 10 (integer) =

Donne un rsultat de 36, vous oubliez que de fait, la multiplication s’effectuant en fait en double (cela tient la manire dont fonctionne le language), le rsultat est en fait 72.00, de type double, mais en termes de bits, quelque chose comme 71.999999. C’est ce que Markus a tent de vous expliquer.

Si vous faites

system.debuglog(str(3.6*20))

vous obtenez bien

72.

Mais c’est un type double, pas Integer. La conversion implicite que vous obtenez par gal quivaut en fait floor().

Peut tre vous sembl-je vhment, mais il me semble important que vous ralisiez que le rsultat est correct, mais que c’est votre affectation un integer qui cre le problme.

Il est trs important lorsque l’on programme de ne rien laisser au hasard, et d’tre conscient des oprations que l’on utilise.

Comprenez que j’ai coeur de vous aider mieux programmer. C’est important pour vos futurs projets.

For the rest of readers: I am sorry to post in a Foreign language, but basically, I just translated what I posted before, as a courtesy to the OP.