Math/syntax question

Monkey Forums/Monkey Programming/Math/syntax question

Lillpeter(Posted 2015) [#1]
Hi guys. I've run into a silly little problem that I can't figure out. I'm trying to extract a float value using the following code:

scaleFactor:Float = DeviceHeight() / myObjectHeight

For some reason the sum end up as either 1.0 or 0.0. Why is that? I suspect it is because my input variables are both Ints, but so what? Shouldn't 4 / 3 logically return 1.333... if the target variable is a float? Is there perhaps some kind of typecasting I need to do in the process?

PS. How do I embed code properly in forum posts. I have found no info about how to do that?

Regards Peter


degac(Posted 2015) [#2]
Function Main:Int()
	Local DH:Int=1024
	Local myObjectHeight=25
	Print "DH : "+DH
	Print "Ratio : "+DH / myObjectHeight
	Print "Ratio : "+Float(	DH)/myObjectHeight
end

You need to 'cast' the result you want


ImmutableOctet(SKNG)(Posted 2015) [#3]
What's happening is what you're thinking, it's performing a division using two integer operands. Afterward, it performs an implicit conversion to floating point. In a lot of cases, this can actually be favorable, as ALUs are faster at division. But, since you need floating point accuracy, you'll need to perform a static cast. Static casts allow you to explicitly convert from one type to another. For example an object of any class is statically cast-able to any of its super classes or interfaces. This can even be done implicitly, meaning you don't need to use the casting syntax.

Casting can be done with a "function call"-like syntax using the type. Despite the syntax, these are not functions.

For example:


To do what you're looking for, you want to cast to floating-point. This can be done either by casting both operands as floats manually, or by casting the first, and using implicit conversion for the second.

So, something like this:


As I said, casting the second operand is optional here. Just be careful with more advanced code, where the intent could be misconstrued.

Here 'scaleFactor' is being assigned to our casted value from 'DeviceHeight'. Since I used the type inference operator ' := ', this will be the type of the value we give it. In this case, we provide a value distinguishable as a 'Float'. Once the assignment is done, we perform division using 'scaleFactor'. Since 'scaleFactor' is floating-point, we get this as a floating-point operation. If 'myObjectHeight' was a 'Float', this would also produce a floating-point value.

Here's an incorrect example, showing bad casting practice when expecting this effect:


Here, 'Z' is a 'Float', but only because it was declared (Or in this case, inferred) as a 'Float'. The operation was done using two 'Int' variables, so the result is an 'Int'.

Now, what if we make 'Y' a 'Float'?


Now, 'Y' is of type 'Float' because the compiler inferred it as such. This is because a numeric literal containing a decimal point is considered to be floating-point. But what about 'Z'? Is it a 'Float'? And if so, is it the right value?

The answer is yes. The value provided from "X / Y" was from an 'Int' interacting with a 'Float'. This applies everywhere when mixing the two types. Adding, subtracting, multiplying, etc. But, the cast performed wasn't necessary here. But, some people may still do this for the sake of leaving their code less ambiguous.

Regardless, it isn't needed, and we could use ' := ' to infer the type. We could also make this more descriptive in the same light as the previous example by simply using the type 'Float' for 'Z'.



As a side note, the forum codes can be found when making normal posts. For some reason they don't show up when making a thread. You'll want "[codebox]" for your usual cases. There's also "[code]" if you need it.


Gerry Quinn(Posted 2015) [#4]
Another way of doing it, which you might find simpler, is making at least one of the values in your calculation a float. Monkey will then convert the others to floats there, rather than when it's passing on the result to scaleFactor (at which point it's too late).

Example:



This will give you 1.33


ImmutableOctet(SKNG)(Posted 2015) [#5]
@Gerry Quinn: I'm glad you brought this up. I was originally going to say something about this is my own post, but I thought it was long enough already. This can actually provide some useful speedups.


Lillpeter(Posted 2015) [#6]
Wow, thanks! This really clarify things for me.


Steve Ancell(Posted 2015) [#7]
I always use floats for all elements involve in any operations that do dividing, unless something actually needs to be integer. I don't run into division problems that way.