Strange INT behavior
Blitz3D Forums/Blitz3D Beginners Area/Strange INT behavior
| ||
Should this: a# = Int(123.456) + (Int(123.456)/1000) Print a# print out 123.123? David William Edwards |
| ||
No it should print out 123.0 |
| ||
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) |
| ||
No, the 2nd part isnt returning an int as the brackets are wrong for it. |
| ||
OK, well, hopefully the idea is clear anyway ... One of the arguments has to be a float. |
| ||
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 ? |
| ||
Because a# = int(123.456) is being rounded down since you are converting to an int. |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
So Floats have only 6 digits of precision? I didn't find this in the manual or a workaround. |
| ||
I'm sure floats have more than 6 digits of precision. Blitz would be useless otherwise. |
| ||
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. |
| ||
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. |
| ||
Koriolis I think he was talking about after the decimal point. |
| ||
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. |
| ||
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. |
| ||
Tested this out, and it seems to be only 6 digits.... strange. This a bug maybe?? |
| ||
"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] |
| ||
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. |
| ||
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 |
| ||
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 |
| ||
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! |
| ||
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] |
| ||
"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. |