Author Topic: INT not always doing the INT thing  (Read 3556 times)

0 Members and 1 Guest are viewing this topic.

Offline zaadstra

  • Newbie
  • Posts: 78
    • View Profile
INT not always doing the INT thing
« on: April 26, 2021, 04:38:55 pm »
Hi all,

I have a little program copying stuff and printing progress.  The GB's are rounded to one decimal, like 89.3 GB.
Sometimes the number prints a lot of garbage, like 89.90000000001 GB.  I narrowed it down to the code below, which shows the same behaviour.

Code: QB64: [Select]
  1. allfolderstotal&& = 22123456789
  2. FOR sizedone&& = 1 TO allfolderstotal&& / 2 STEP RND * 100000000
  3.    _DELAY 0.050
  4.    PRINT STR$(INT(sizedone&& / 107374182.4) / 10) + " GB (" + LTRIM$(STR$(INT(sizedone&& / allfolderstotal&& * 100))) + "%)"

Part of the output:

Code: Text: [Select]
  1.  8.2 GB (39%)
  2.  8.2 GB (40%)
  3.  8.300000000000001 GB (40%)
  4.  8.4 GB (40%)
  5.  8.4 GB (41%)
  6.  8.5 GB (41%)
  7.  8.6 GB (41%)
  8.  8.6 GB (42%)
  9.  8.7 GB (42%)
  10.  8.800000000000001 GB (42%)
  11.  8.800000000000001 GB (43%)
  12.  8.9 GB (43%)
  13.  9 GB (43%)
  14.  9 GB (44%)
  15.  9.1 GB (44%)
  16.  9.1 GB (44%)
  17.  9.2 GB (44%)
  18.  9.300000000000001 GB (45%)
  19.  9.300000000000001 GB (45%)
  20.  9.4 GB (45%)
  21.  9.5 GB (46%)

The interesting this is that the abnomalies always are on the same spots.   I tested with QB64 v1.4 32 and 64 bit, and v1.5 64 bit, all (un)behave the same.
Remove the /2 in the FOR line and you'll see that above 10 GB it does not happen up to 22 GB.  I have a progam screenshot of 89.9000000001 GB ... Again starting with an 8?
What is going on here?   Is it a bug or a feature? :-)

Actually, the /10 divide may be guilty instead of the INT ...
« Last Edit: April 26, 2021, 04:47:23 pm by zaadstra »

Offline zaadstra

  • Newbie
  • Posts: 78
    • View Profile
Re: INT not always doing the INT thing
« Reply #1 on: April 26, 2021, 04:53:32 pm »
Update, indeed it is not the INT but the division:

Code: QB64: [Select]
  1. allfolderstotal&& = 300
  2. FOR sizedone&& = 1 TO allfolderstotal&& STEP RND * 2
  3.    _DELAY 0.050
  4.    PRINT STR$(sizedone&& / 10) + " GB (" + LTRIM$(STR$(INT(sizedone&& / allfolderstotal&& * 100))) + "%)"

Code: Text: [Select]
  1.  8 GB (26%)
  2.  8.1 GB (27%)
  3.  8.2 GB (27%)
  4.  8.300000000000001 GB (27%)
  5.  8.4 GB (28%)
  6.  8.5 GB (28%)
  7.  8.6 GB (28%)
  8.  8.7 GB (28%)
  9.  8.800000000000001 GB (29%)
  10.  8.9 GB (29%)
  11.  9 GB (30%)
  12.  9.1 GB (30%)
  13.  9.2 GB (30%)
  14.  9.300000000000001 GB (31%)
  15.  9.4 GB (31%)
  16.  9.5 GB (31%)
  17.  9.6 GB (32%)
  18.  9.7 GB (32%)
  19.  9.800000000000001 GB (32%)
  20.  9.9 GB (33%)
  21.  10 GB (33%)

Sorry, INT! :-)

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: INT not always doing the INT thing
« Reply #2 on: April 26, 2021, 05:47:52 pm »
If you only want one decimal place, use INT(value * 10) / 10.

For example:

3.000000001 becomes 3.0
3.123456789 becomes 3.1

And so on.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline zaadstra

  • Newbie
  • Posts: 78
    • View Profile
Re: INT not always doing the INT thing
« Reply #3 on: April 26, 2021, 06:12:30 pm »
If you only want one decimal place, use INT(value * 10) / 10.

For example:

3.000000001 becomes 3.0
3.123456789 becomes 3.1

And so on.

That is what I am doing, the /10 is in the 107374182.4 value.  A gigabyte is 1073741824.  I just found out it is not the INT causing the issue, but the /10 division.  This is for the guru's to determine what it is I guess...
I'm sure your example will show the same weird behaviour somewhere, as I demonstrated in post #2.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: INT not always doing the INT thing
« Reply #4 on: April 26, 2021, 06:14:38 pm »
Yeah, I've had issues with that one too. In my case it happens around .07 in exponential notation. I've taken to calling it the "7E-02 bug". Although I'm sure it occurs elsewhere as well.

The following is a snippet of code from one of my projects. In working with very large distance displays, I would convert from kilometers to astronomical units for fitment in a display space. I used the very algorithm that Steve mentioned, but it still tries to throw extra digits at around any number that resolves to about .07

Both INT and _ROUND would do the same thing. My solution was to wait until I was well past the bug before making my change, since I still had display space for it.

Code: QB64: [Select]
  1.             IF d## < 12000000 THEN '                 we change to 12 mil to skip over the 7E-02 bug
  2.                 d$ = STR$(INT(d##)) + "km"
  3.             ELSE
  4.                 d$ = STR$(_ROUND((d## / KMtoAU) * 100) / 100) + "AU" 'yields 7.000000000.... between .06 & .08 both _round & INT do it
  5.             END IF
  6.  

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: INT not always doing the INT thing
« Reply #5 on: April 26, 2021, 10:17:00 pm »
Try doing the math outside the PRINT.  like this;

Code: QB64: [Select]
  1. FOR sizedone&& = 1 TO allfolderstotal&& STEP RND * 2
  2.  _DELAY 0.050
  3.  A! = (sizedone&& / 10)
  4.  B! = (INT(sizedone&& / allfolderstotal&& * 100))
  5.  PRINT A!; " GB ("; B!; "%)"
  6.  

That fixed the floating point issue on my end. you might need to reformat the PRINT to get the output to look like you want but the extra numerals no longer show up on my end anyway.

I believe when you do the math in the PRINT statement it converts the numbers to floating point and that is where you start to see that .0000...1 , or there abouts, number showing up.
Granted after becoming radioactive I only have a half-life!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: INT not always doing the INT thing
« Reply #6 on: April 27, 2021, 07:19:13 am »
Try doing the math outside the PRINT.  like this;

Code: QB64: [Select]
  1. FOR sizedone&& = 1 TO allfolderstotal&& STEP RND * 2
  2.  _DELAY 0.050
  3.  A! = (sizedone&& / 10)
  4.  B! = (INT(sizedone&& / allfolderstotal&& * 100))
  5.  PRINT A!; " GB ("; B!; "%)"
  6.  

That fixed the floating point issue on my end. you might need to reformat the PRINT to get the output to look like you want but the extra numerals no longer show up on my end anyway.

I believe when you do the math in the PRINT statement it converts the numbers to floating point and that is where you start to see that .0000...1 , or there abouts, number showing up.

Or use PRINT USING to format for a single decimal place.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline zaadstra

  • Newbie
  • Posts: 78
    • View Profile
Re: INT not always doing the INT thing
« Reply #7 on: April 27, 2021, 08:53:58 am »
Indeed, doing the math outside does the trick (why??):

Code: QB64: [Select]
  1. allfolderstotal&& = 300
  2. FOR sizedone&& = 1 TO allfolderstotal&& / 2 STEP RND * 2
  3.    _DELAY 0.050
  4.    x = sizedone&& / 10
  5.    PRINT STR$(x) + " GB (" + LTRIM$(STR$(INT(sizedone&& / allfolderstotal&& * 100))) + "%)"
  6.  


Code: Text: [Select]
  1.  8 GB (26%)
  2.  8.1 GB (27%)
  3.  8.2 GB (27%)
  4.  8.3 GB (27%)
  5.  8.4 GB (28%)
  6.  8.5 GB (28%)
  7.  8.6 GB (28%)
  8.  8.7 GB (28%)
  9.  8.8 GB (29%)
  10.  8.9 GB (29%)
  11.  9 GB (30%)
  12.  9.1 GB (30%)
  13.  9.2 GB (30%)
  14.  9.3 GB (31%)
  15.  9.4 GB (31%)
  16.  9.5 GB (31%)
  17.  9.6 GB (32%)
  18.  9.7 GB (32%)
  19.  9.8 GB (32%)
  20.  9.9 GB (33%)
  21.  10 GB (33%)

This printing actually goes to _TITLE so print using won't help here. And in many cases print using is not my friend ;-)

Thanks for thinking on this!

FellippeHeitor

  • Guest
Re: INT not always doing the INT thing
« Reply #8 on: April 27, 2021, 09:01:17 am »
Just an aside: Windows limits changing _TITLE after a few hundred calls.

FellippeHeitor

  • Guest
Re: INT not always doing the INT thing
« Reply #9 on: April 27, 2021, 09:02:34 am »
Or was that _ICON?... Can't remember clearly now.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: INT not always doing the INT thing
« Reply #10 on: April 27, 2021, 09:16:15 am »
Indeed, doing the math outside does the trick (why??):

PRINT is about the world's most complicated set of code.  The code to launch nuclear missiles can't be much more complex than PRINT is.  There's a ton of things which it does wonky, but they're hard to sort out to try and fix.

In this case, let's look at your QB64 code and the translated C-code which we make from it:

QB64 code:
Code: QB64: [Select]
  1. PRINT STR$(INT(sizedone&& / 107374182.4) / 10) + " GB (" + LTRIM$(STR$(INT(sizedone&& / allfolderstotal&& * 100))) + "%)"

Translated code:
Code: C++: [Select]
  1. qbs_set(tqbs,qbs_add(qbs_add(qbs_add(qbs_str((double)(floor(*__INTEGER64_SIZEDONE/  107374182.4E+0 )/  10 )),qbs_new_txt_len(" GB (",5)),qbs_ltrim(qbs_str((long double)(floor(*__INTEGER64_SIZEDONE/ ((long double)(*__INTEGER64_ALLFOLDERSTOTAL))* 100 ))))),qbs_new_txt_len("%)",2)));

Isn't that a nice a simple little line of code to try and sort out??  And which part of that is causing the issue with the math itself is in there somewhere....  But where?

My first guess would be at asking, "Why is the first math cast to a double, while the rest is to long doubles?  (See the (double) vs the (long double)?) 

My second question is:  If we were to change that to long double for testing, exactly where in the QB64 source would we make that change with the translation???  (And from my past experience with PRINT here, my answer would probably be, "We don't.  We hide from trying to sort out PRINT issues and leave them to someone else to figure out!!")



https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: INT not always doing the INT thing
« Reply #11 on: April 27, 2021, 09:22:43 am »
Just an aside: Windows limits changing _TITLE after a few hundred calls.

Code: [Select]
FOR i = 1 TO 1000000
    _LIMIT 1000
    _TITLE STR$(i)
NEXT

Just let the above run for about a minute and had no issues with _TITLE.  Numbers updated as expected. 

I remember there was some issues with repeated calls to _TITLE, but if my memory is correct, those are from the differences in QB64 strings and C-strings.  _TITLE doesn't set a length for the strings (or at least, I don't think it does), so you may run into issues if you don't null terminate the title with a CHR$(0).  (At least, that's the way I remember correcting the issue in the past, when I bounced into it.)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline zaadstra

  • Newbie
  • Posts: 78
    • View Profile
Re: INT not always doing the INT thing
« Reply #12 on: April 27, 2021, 01:01:05 pm »

Isn't that a nice a simple little line of code to try and sort out??  And which part of that is causing the issue with the math itself is in there somewhere....  But where?

My first guess would be at asking, "Why is the first math cast to a double, while the rest is to long doubles?  (See the (double) vs the (long double)?) 

My second question is:  If we were to change that to long double for testing, exactly where in the QB64 source would we make that change with the translation???  (And from my past experience with PRINT here, my answer would probably be, "We don't.  We hide from trying to sort out PRINT issues and leave them to someone else to figure out!!")

Haha that is a nice line of C code, I really cannot make any chocolat of that ...

There are different var types as disk sizes really need long doubles, and the result is not higher than a couple of hundreds and one decimal.  I'm really not an expert on those types, and besides the wiki page on variable types I haven't ever read a comprehensive text on this.
Usually I think if I won't violate size limits and usually it works fine!

About the compiler - that's not my piece of cake!  I believe there is some rough part around this as removing the math and giving a variable with the same value is a resolution to the issue.
This is not the first time that writing the code af bit differently fixes an issue ... part of the game :-)

Offline zaadstra

  • Newbie
  • Posts: 78
    • View Profile
Re: INT not always doing the INT thing
« Reply #13 on: April 27, 2021, 01:04:47 pm »
Just an aside: Windows limits changing _TITLE after a few hundred calls.

What should I expect?  I haven't seen strange behaviour on _TITLE and I'm sure I've reached the hundreds of calls ....  I only know I must not set _TITLE to soon at the start of the program otherwise it is missed / not working.
I (mis) use the title bar instead of the old times statusbar line 25 (which still works).