Division operation

tlk
So first off I'm still using 5.4. I'm sure most are probably using 5.5 now, but I haven't made the switch yet, and honestly am just as curious as to whether the same thing happens with it as what I'm seeing with 5.4 if someone's willing to try. I'm working on a combat system which utilizes lots of integers for HP, accuracy, damage, etc, and has a lot of mathematical operations going on to measure everything against each other and calculate results, and I noticed that when I divide an odd number it always rounds the result down. Example:

x = 7
y = x / 2
msg (y)


should, to my way of thinking, return 3.5, but in practice returns 3. Thanks to the insight of my girlfriend (credit where credit's due) I've determined that you can make it work by setting x to equal 7.0 instead of just 7, which I'm pretty sure will resolve the problems it creates for me, but I still just don't understand why it doesn't work without it. Particularly when this:

x = 7
y = x - 1.5
msg (y)


returns 5.5 without the need for x to be 7.0. Any thoughts? Am I missing something simple?

george
No, this is common in programming but is kind of assumed rather than stated most of the time. Integer division will return integers. Floating point (i.e. '7.0') will return floating point. Any operation using floating point will generally return floating point.

jaynabonne
To expand on George's response, integers and double (aka floating point) values behave differently when being operated on. Integer values will always return integer results, and operations on doubles return "double" results.

What seems to be the case is that Quest (or its expression parser) infers the type of a variable or attribute by what you assign to it. For example, if you do:

somevar = "hello"

then somevar will be a string. Similarly, if you do:

somevar = 8

then somevar will be an integer, and so on for "somevar = 8.0" and it being double.

When you have:

x = 7
y = x / 2

all the operands are integers, and so the result will be an integer value. By default, integer operations truncate (they drop any fractional part).

When you have:

x = 7
y = x - 1.5

x will be an integer value, but when you go to compute y, you have both an integer and a double. What should happen? What does happen is that the integer value is "promoted" to a double, and then the operation is performed entirely in floating point, with a double result. That's why it "works" in that case.

Promotion happens in other cases as well, usually in the way you'd want. If you do:

x = 7
s = "Hello" + x

then "s" will be "Hello7". In that case, the integer has been promoted to a string. Similarly,

x = 7.5
s = "Hello" + x

should yield "s" being "Hello7.5".

For your initial example, any of the following should give you the result you want (as far as the y value):

x = 7.0
y = x / 2

x = 7
y = x / 2.0

x = 7.0
y = x / 2.0

In all three cases, the y computation will be promoted to floating point, as long as at least one operand is floating point. The x value will vary depending on what you assign to it.

HegemonKhan
@Jay,

you mean GEORGE's response (in this case, it's not me posting a response ~ I didn't get here soon enough, lol), unless you mean from a post of mine somewhere else, where I explained integers vs doubles (floats~floating points).

------

just to add a small comment:

it depends on the underlying code, so it depends how it is programmed to compute (which you can change if you're good at it):

truncate (drop the decimal~fraction part of it) ~ as Jay shown, is how quest does it
the actual answer (as an integer or double)
rounding down or up (up >= X.5 or down < X.5)

-----

the other big problem with coding (just as it is with yourself doing a math problem) is:

rounding (precision)

as if you round early in a computation, due to how they deciding to code the rounding, it can completely messes up the final result, to a totally wrong answer, which can thus completely mess up your created game obviously.

if you're a math+programming nerd, it's fun to see how your calculators are programmed with its rounding.

jaynabonne
<doh!> My bad. And I have no idea why either... lol Many apologies to all.

tlk
Ahhhhh, that clears so much up for me. Just my lack of any real programming knowledge again. Thanks all!

The problem I was running into was trying to give three options, each with some percent chance of happening based on player attributes, which when added together would add up to 100%. Under certain circumstances value A would be halved and value B would make up the difference, but when I halved the former and then halved it again to figure out how much to add to the latter, I ended up with the three adding up to only 99% because of the rounding. Hardly game-breaking, but the kind of thing I would notice and would bug me if I were playing a game (the percentages are shown to the player to aid in deciding what to do).

All of Jay's suggestions work for my purposes, but just as an observation I've noticed that you can't pass floating point into the GetRandomInt function, as it returns an error. I'm assuming this is true of other integer-based functions as well, but haven't tried any. It doesn't cause me a problem, but I thought it was worth pointing out just in case anyone else was both trying to avoid the truncation and using that function.

Quick related question: is there a way to tell if an integer is an even or odd number? I've looked around the function list and on the forums and can't find one.

EDIT: Nevermind, just realized you can do it with mod (%), duh. For some reason I was only looking for a function.

HegemonKhan
you could try leaving the value used (in 'GetRandomInt' for example) as a ratio~fraction (not sure if this will work or not though):

GetRandomInt (0,7/2)

instead of:

GetRandomInt (0,3.5)

jaynabonne
Probably more than you want to know, but...

There are four functions for converting doubles to integers: truncate, floor, round and ceiling.

"truncate" returns the integer with the fractional part dropped (rounded toward 0).
truncate(3.1) = 3
truncate(3.5) = 3
truncate(3.7) = 3
truncate(4.0) = 4
truncate(-3.1) = -3

"floor" returns the integer that is less than or equal to the value passed (rounded toward negative infinity):
floor(3.1) = 3
floor(3.5) = 3
floor(3.7) = 3
floor(4.0) = 4
floor(-3.1) = -4

"ceiling" returns the integer that is greater than or equal to the value passed (rounded toward infinity):

ceiling(3.1) = 4
ceiling(3.5) = 4
ceiling(3.7) = 4
ceiling(4.0) = 4
ceiling(-3.1) = -3

"round" returns the integer which is the double value rounded toward 0 if fractional part is < 0.5, otherwise away from 0:

round(3.1) = 3
round(3.5) = 4
round(3.7) = 4
round(4.0) = 4
round(-3.1) = -3
round(-3.5) = -4

(I hope I got all those right.)

So for your GetRandomInt case, assuming the number is always greater than 0, you could use truncate or floor. I assume if the value is 3.5, you don't want the random numbers to go up to 4... :)

There is also a cast operator, but you can explore that on your own (or ask me, if you're really curious).

HegemonKhan
another thing you could do, is to create your own function 'GetRandomDouble', but this probably takes a good bit of coding ability.

jaynabonne
Ironically, I just discovered (while trying to implement the above suggestion) that there is already a function called GetRandomDouble. (This fact caused me untold grief as it would never find my function inside an expression and kept complaining about parameters.) This function looks like this:

value = GetRandomDouble()


and returns a value between 0.0 and 1.0. This can be used to create a general purpose GetRandom function:

  <function name="GetRandom" parameters="lower,upper" type="double">
return (GetRandomDouble()*(upper-lower) + lower)
</function>

For those times when you do want a full floating-point random number...

Silver
Thread necromancy - ignore. I'm afk but need to add this to my records. It's radio rental, but looks useful.

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums