Strange INT behavior

Blitz3D Forums/Blitz3D Beginners Area/Strange INT behavior

DaveEdwards(Posted 2004) [#1]
Should this:

a# = Int(123.456) + (Int(123.456)/1000)
Print a#

print out 123.123?

David William Edwards


eBusiness(Posted 2004) [#2]
No it should print out 123.0


Warren(Posted 2004) [#3]
No, because dividing an INT by an INT results in an INT. If you want a floating point result, one of the sides of the division must be a float. You can try these options:

a# = Int(123.456) + (Int(123.456)/1000.0)

or

a# = Int(123.456) + Float(Int(123.456)/1000)


smilertoo(Posted 2004) [#4]
No, the 2nd part isnt returning an int as the brackets are wrong for it.


Warren(Posted 2004) [#5]
OK, well, hopefully the idea is clear anyway ...

One of the arguments has to be a float.


DaveEdwards(Posted 2004) [#6]
Thanks! But then why does:

a# = Int(123.456)
b# = Int(123.456)/10000.0
Print a# + b#

print out: 123.012 and not 123.0123 ?


Perturbatio(Posted 2004) [#7]
Because a# = int(123.456) is being rounded down since you are converting to an int.


jhocking(Posted 2004) [#8]
Logically (well, logically to me anyway) if you want a floating point result, you should be doing math on floating point values. Why you're using Int() to convert floating point values to integers before doing the math, and then converting back to a floating point value, is beyond me. In fact, the more I think about it, the more ludicrous it seems.


DaveEdwards(Posted 2004) [#9]
Maybe I'm using the wrong command, but I'm using INT to round a floating point. I've looked at Ceiling and Floor, but that doesn't seem to work the way I want them to.


Stevie G(Posted 2004) [#10]
Not true, you're using the right command but remember that blitz's floats have quite a low precision. Try a#= 123.0123 and print a. You'll notice that this is also 123.012.

It's a bit of a pain to be honest but there you go.

Stevie.


jhocking(Posted 2004) [#11]
Int() doesn't just round the number, it actually converts the number to an integer (ie. not floating point anymore.) Ceiling and Floor are the proper commands for rounding; that they aren't working the way you expect is probably due to how they behave with negative numbers. For example, -2.0 is lower than -1.1 so Floor#(-1.1) will give you -2.0; if you wanted/were expecting -1.0 (ie. simply replacing everything after the decimal point with 0) you have to use an If statement to check the value first and then use Floor or Ceiling as appropriate.


DaveEdwards(Posted 2004) [#12]
So Floats have only 6 digits of precision? I didn't find this in the manual or a workaround.


Warren(Posted 2004) [#13]
I'm sure floats have more than 6 digits of precision. Blitz would be useless otherwise.


Perturbatio(Posted 2004) [#14]

For example, -2.0 is lower than -1.1 so Floor#(-1.1) will give you -2.0; if you wanted/were expecting -1.0 (ie. simply replacing everything after the decimal point with 0) you have to use an If statement to check the value first and then use Floor or Ceiling as appropriate.



or you could do something like:
a# = 1.123
Print Floor(Abs(a#)) Or a#

*edit*
then again, forget that one.


Koriolis(Posted 2004) [#15]
Not much more. When we say 6 digits, we're talking in decimal numbers. A floating point value has a mantissa of 23 bits (if you don't count the sign), which makes the max number be 8388608. So that's between 6 & 7 digits.

[EDIT]Crosspost, this was a reply for EpicBoy.


Warren(Posted 2004) [#16]
Koriolis

I think he was talking about after the decimal point.


Koriolis(Posted 2004) [#17]
Me too. A float is of the form S*M*2^E.
S: sign (-1 or 1), 1 bit
M: mantissa, a 23 bits integer
E: exponent, a 8 bits integer

The size of M directly dictates the maximum number of digits after the decimal point.

[Edit:] Corrected myself, it's a 8 bits long exponenet, not 7 bits.


Warren(Posted 2004) [#18]
Ahh, OK, I'm tired.

Well, Blitz seems to handle any calcs I throw at it, so I'd still be surprised if that was all the precision that floats had. And if it is, I guess that's fine since, as I say, it seems to work. Heh.


Ross C(Posted 2004) [#19]
Tested this out, and it seems to be only 6 digits.... strange. This a bug maybe??


sswift(Posted 2004) [#20]
"Ceiling and Floor are the proper commands for rounding; that they aren't working the way you expect is probably due to how they behave with negative numbers. For example, -2.0 is lower than -1.1 so Floor#(-1.1) will give you -2.0; if you wanted/were expecting -1.0 (ie. simply replacing everything after the decimal point with 0) you have to use an If statement to check the value first and then use Floor or Ceiling as appropriate."


Ugh! I'll have to remember that. That sucks.

So we can't count on Int(-256.56) to return -256, and we can't cound on floor(-256.56) to return -256, and we obviously don't want to have to use an IF statement every time we do a math operation.

I wonder what Blitz does if you go a = -256.56. Does it round up/down, or does it just round down? I guess I'll have to test it...

Oh wonderful. It rounds both up and down like Int(). WHY MARK?! WHY?! WHY MUST YOU TORMENT ME SO?!

Converting to int should discard the remainder. That allows such wonderful constructs as:

A# = B# - Int(B#)

Which would give you the fractional part of a number and which I used to use constantly, before Blitz.

And:

A# = Int(B#)

Which of course would give you the integral part of the number only.

But how do I do these with this weird setup? I can't think of a way without using if statements.



[edit]

Actually, I just realised that with negative numbers you want floor() to round "up".

Here's why. Imagine you have a grid, with each tile being 1 unit wide. So you have a tile start at 0, 1, 2, 3, 4, etc.

Now, if you go leftwards, you hit negative tile starting locations... -1, -2, -3...

Now imagine you have a point at 0.5. If you want to find out which tile that is at, you use floor() and that rounds it down to 0. So you know you're at the tile that starts at 0.

But what if you have a point at -0,5? Well, rather than it rounding "down" to 0, which would be wrong in this case, you want it to round "up" to -1.

So floor really does "round down" properly because -1 is less than -0.5.

Hey I never said I got A's in algrebra. :-) (Actually, I got F's!)

[/edit]


Floyd(Posted 2004) [#21]
I can't think of a way without using if statements.

So use If statements.

The exact behavior of Int, Floor and Ceil is in the docs.
The only confusing thing is that Int actually means round, not the traditional 'chop'.

Calculating chop is certainly slower than Int. But this is unavoidable. Intel CPUs do not have a built-in command for this. So even if Blitz changed the behavior of Int to chop it would still have to be done by calculation.


Perturbatio(Posted 2004) [#22]
Function ChopDown#(num#)
	If num < 0 Then
		Return Floor(Abs(num#))
	Else
		Return Floor(num#)
	EndIf
End Function

Function ChopUp#(num#)
	If num < 0 Then
		Return Ceil(Abs(num#))
	Else
		Return Ceil(num#)
	EndIf
End Function



Floyd(Posted 2004) [#23]
The implied meaning of the word Chop is that the digits after the decimal point are lopped off.
Function Chop( x# )
	If x > 0 
		Return Floor( x )
	Else
		Return Ceil( x )
	End If
End Function



sswift(Posted 2004) [#24]
Oh I'm sure calling a Blitz function in the middle of a high speed function that has to operate on millions of points will be reeeeal fast. :-) Specially if it's got an if statement in there!


sswift(Posted 2004) [#25]
I did a test, and I found something interesting.

B# = A# - Floor(A#) will return the absolute value of the fractional part of A#.

In other words, if A# is 1.5, you get 0.5. If A# is -0.5, you get 0.5. I tried this with .4 and .6 as well both positive and negative to be sure it works in all cases, and it does.

[edit]
Whoops, scratch that, I just realised I tested the positive case twice and failed to test two of the negative cases, which did not work right.
[/edit]


eBusiness(Posted 2004) [#26]
"B# = A# - Floor(A#) will return the absolute value of the fractional part of A#."

No it will return the number in the interval [0;1[ that will make a whole number if subtracted from a. This is what is calculated fastest, and what you will need for your tile example.