Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Officially goin out of my mind. Trivial INT problem
#1
Doggone it, I couldn't figure out why this program wasn't working, and it boils down to this:

Code: (Select All)
x = 35.51
y = x * 100
z = Int(y)
Print x, y, z

WTH, over? My results are: 35.51    3551    3550

How does that make any sense? Why is Int(3551) not simply 3551??
Reply
#2
Floating point math. Y is probably 3550.99999999999999, which is enough to print 3551, but which INT will round down to 3550.

Try making the variables DOUBLE or FLOAT types.
Reply
#3
I don't know if IEEE was ever involved with 8-bit computers. But migrating from Color Computer to any IBM PC-Compatible object almost destroyed my faith in "INT()".

@bert22306 I might have been just like you thinking "INT()" should always just shave off the decimal part of a floating-point number, even a negative number. Like "-54.54" should just give "-54", right? But sadly QuickBASIC didn't work that way, "INT()" was made to work a lot like "floor()" in C. When I saw this in the "QuickBASIC Bible" book that I used to own, I weeped. It suggested using "FIX()" for what I wanted. What is even more sad is that more applications created with QuickBASIC and its descendants now rely on how "INT()" works influenced by IEEE, instead of how it worked on a given 8-bit computer.

This behavior has come down to what you have just discovered which is just sad. It could bring someone else (me on some days) to process a floating-point number as a string, search for the darned decimal point and just return whatever is "west" of that decimal point starting with the sign if it exists.

BTW I just don't know why "_ROUND()" was invented LOL, totally worthless to me.
Reply
#4
Thanks, guys, I kind of finally thought of that. This works:

Code: (Select All)
x = 35.51
y& = x * 100
z = Int(y&)
Print x, y&, z

Aaargh.
Reply
#5
Here's the problem, @bert22306 :

Code: (Select All)
x = 35.51
y = x * 100
z = Int(y)
Print Using "######.##############"; x
Print Using "######.##############"; y
Print Using "######.##############"; z

Remember, PRINT rounds and truncates and only displays a maximum of 8 digits or so of your number -- which is why the results format to look like what you'd exoect. PRINT USING, as above, gives you a much more accurate depiction of what the true values of your variables are.

35.51 has no perfect representation in binary math. Multiplying an imperfect representation leads to another imperfect representation.

Everything is working 100% as expected here, even if PRINT, by itself, makes that a little difficult to see and understand.
Reply
#6
And notice this little solution, that I mentioned above:

Code: (Select All)
DefDbl A-Z
x = 35.51
y = x * 100
z = Int(y)
Print Using "######.##############"; x
Print Using "######.##############"; y
Print Using "######.##############"; z
Reply
#7
My sympathies to Bert, this is so not intuitive! Why y not 35.5100000000000000? Yikes!

String Math time! ;-))
b = b + ...
Reply
#8
Ahhhhh...
Code: (Select All)
s$ = Str$(35.51)
Print s$
Print Val(s$) * 100
a = Val(s$) * 100
Print Int(a)
like magic!

Another math problem solved with String Math, Pete would be proud!
b = b + ...
Reply
#9
(10-31-2022, 05:04 PM)bplus Wrote: My sympathies to Bert, this is so not intuitive! Why y not 35.5100000000000000? Yikes!

Because computers keep track of numbers in BASE 2 binary format.

Here's an exercise for you:  Give me the binary value that represents 0.1.  If you can do that, you'll see what the issue is, forevermore.

Powers of 2...
16  (let's just start with 2 ^ 4)  -- too large
8 (2 ^ 3) -- too large
4 (2 ^ 2) -- too large
2 (2 ^ 1) -- too large
1 (2 ^ 0) -- too large
.5 (2 ^ -1) -- too large (for 0.1, it is. Tongue )
.25 (2 ^ -2) -- too large
.125 (2 ^ -3) -- too large
.0625 (2 ^ -4) -- TOO SMALL!!

WTH??  We just went from too large a value to represent 0.1, to too small a value!  So how do we fix this discrepancy??  Surly we aren't going to settle for 0.0625 as being "close enough" to represent 0.1!!  Are we??

Of course not!  We continue on, adding smaller halves to our value to try and get as close to 0.1 as possible!

0.03125 (2 ^ -5) -- too small, but when added to 0.0625, we get:  0.0935 -- that's a lot closer to 0.1 than just 2 ^ -4 by itself.

0.00011&B is much closer to 0.1 than 0.0001&B -- but let's keep on adding halves!  Maybe we can eventually find the PERFECT value that represents 0.1!!

(And, at this point, I'll leave it up to you to try so that you can learn what the issue is and why binary -- ie FLOATING POINT -- values are imprecise and must be handled with care.)
Reply
#10
.1 decimal =
.00011 repeat 0011 forever (can't draw a bar over top of 0011)
   

like 1/3 = .3 with bar ontop of 3.

Another question solved with string math! ;-))

Just having fun, I know we can't do "bars on top" with our binary computers.
b = b + ...
Reply




Users browsing this thread: 1 Guest(s)