|
Post by sebavoda on Apr 30, 2024 20:02:45 GMT
I wrote a program that is not working as intended.
FOR i = 0 TO 2
s = 10 ^ (-i)
FOR j = 0 TO 5 STEP s
PRINT s, j, (j - s)
NEXT j, i
I am expecting for s to be 1, 0.1 or 0.01 It is. I also expect to calculate and print j-s and there it fails after few steps. The last line I expect to be
.01 4.99 4.98
However it is
.01 4.990019 4.980019
Am I doing something wrong or it is a bug? From where are there those extra decimals? How to trim them down to two decimals? I mean I want the value to be 4.98 not 4.980019
I am using QB64 Version 2.1 Developement Build From git 47f5044
|
|
|
Post by bplus on May 1, 2024 0:11:27 GMT
maybe this f$(0) = "# " f$(1) = "#.# " f$(2) = "#.## " For i = 0 To 2 s = 10 ^ (-i) For j = 0 To 5 Step s Print Using f$(i); s, Print Using f$(i); j, Print Using f$(i); (j - s) Next j, i
there is some garbage in last digits of single type, print using;format$ as above usually cleans up values for display. welcome sebavoda
|
|
Aaditya Parashar
Full Member
Just somebody with an abnormal coding routine.
Posts: 124
|
Post by Aaditya Parashar on May 1, 2024 4:02:44 GMT
I don't know if this would work on other systems, but with _Float, it works as intended:
Dim As _Float s, J For I = 0 To 2 s = 10 ^ (-I) For J = 0 To 5 Step s Print s, J - s, J Next J, I
|
|
|
Post by sebavoda on May 1, 2024 11:56:42 GMT
Thanks all for your help. The fail is in the step in the second loop, I know. It seems that in the inner loop, at some point i is decremented with s but the substraction is not correct. I do not need to print the values, but to use them further. So, PRINT USING is not useful to me. I tried the _FLOAT statement but it works only for few loop iterations, more than without it.
DIM AS _FLOAT s, j
FOR i = 0 TO 5
s = 10 ^ (-i)
FOR j = 0 TO 5 STEP s
PRINT s, j, (j - s)
NEXT j, i
I want to use a similar loop to call a recursive function (were the print statement is) for these values, up to (5,5) and to use the (j-s) value in that function (it shoud return a value when (j-s)=0). While it did not worked (it exited the program with a crash) because (j-s) never reach 0 after few iterations, I write this test program to see what is wrong with the (j-s) value and so I find the error in the step. I tried the same program in QB7 and it have the same issue, after few iterations, the step do not work properly.
The output for the last iteration (when i=j=5) is
.00001 4.999990000000012 4.999980000000011
Thank you again.
|
|
|
Post by bplus on May 1, 2024 15:24:23 GMT
i know i've been so frustrated by qb64's decimal math that i hace resorted to 2 other ways around.
for dollars and cents values i do all calcs in cents then have a function for inserting the decimal two places into the cents value for display; works as long as you avoid division and stay in range of _integer64 which is 10 million dollars and cents as i recall or 99,999,999.99? i forget.
the other way around is to convert all numbers to strings and do string math with your own routines way slower but 100% accurate!
|
|
Aaditya Parashar
Full Member
Just somebody with an abnormal coding routine.
Posts: 124
|
Post by Aaditya Parashar on May 1, 2024 15:31:23 GMT
This is not a math bug in just qb64, it is a problem just because how computers deal with floating point numbers. We cannot include any external libraries in qb64, so we can just use a Round Function with variable decimal precision: Dim As Single s, J For I = 0 To 5 s = 10 ^ (-I) For J = 0 To 5 Step s J = RoundFloatingPointNumber##(J, I) Print s, J - s Next J Next I Function RoundFloatingPointNumber## (X As _Float, I) RoundFloatingPointNumber## = _Round(X * (10 ^ I)) / (10 ^ I) End Function Hope this helps!
|
|
|
Post by bplus on May 1, 2024 18:35:39 GMT
nice try AP, I had that in my toolbox for awhile until i discovered it was flawed too!
getting decimals right in qb64 is a real bear!
let us see your code for just i = 0 to 2 in the $console:only app, now we can scroll up towards beginning and see the problems
$Console:Only Dim As _Float s, J Dim As Integer i For i = 0 To 2 s = 10 ^ (-i) For J = 0 To 5 Step s J = RoundFloatingPointNumber##(J, i) Print RoundFloatingPointNumber##(s, i), RoundFloatingPointNumber##(J, i), RoundFloatingPointNumber##(J - s, i) Next J Next i Function RoundFloatingPointNumber## (X As _Float, I As Integer) RoundFloatingPointNumber## = _Round(X * (10 ^ I)) / (10 ^ I) End Function
|
|
|
Post by sebavoda on May 2, 2024 8:24:41 GMT
I ran this code and have 3 fails:
.01 .02 .01
.01 .03 .02
.01 .04 .03
.01 .05 .04
.01 .06 .05
.01 7.000000000000001D-02 .06
.01 .08 7.000000000000001D-02
.01 .09 .08
.01 .1 .09
.01 .11 .1
.01 .12 .11
...............
...............
.01 .51 .5
.01 .52 .51
.01 .53 .52
.01 .54 .53
.01 .55 .54
.01 .5600000000000001 .55
.01 .57 .5600000000000001
.01 .58 .57
.01 .59 .58
.01 .6 .59
.01 .61 .6
..............
..............
.01 .76 .75
.01 .77 .76
.01 .78 .77
.01 .79 .78
.01 .8 .79
.01 .8100000000000001 .8
.01 .82 .8100000000000001
.01 .83 .82
.01 .84 .83
The rest is correct. I ran 5 times the code and the result is the same. So, it is not something random, QB64 really means to do that.
|
|
|
Post by sebavoda on May 2, 2024 8:45:39 GMT
The best result so far I came is thanks to B+
DIM AS _FLOAT s, j
FOR i = 0 TO 5
s = 10 ^ (-i)
FOR j = 0 TO 5 STEP s
k = j - s
k$ = STR$(k)
k$ = LEFT$(k$, i + 3)
PRINT s, j, (j - s), VAL(k$)
NEXT j, i
or simply PRINT s, j, (j - s), VAL(LEFT$(STR$(j - s), i + 3)) It returns correct values but is slow, very slow, much much slower than with numbers only, it feels like running code on an 286. But thanks, I will try this solution and I guess it will do.
|
|
|
Post by bplus on May 2, 2024 13:48:01 GMT
sebavoda nice if that works, that looks like a way to keep those dang garbage digits on the end from accumulating errors when using over and over for calc's. it may be slow but i am sure not as slow as 100% string math where powers are so slow as to not even be practical but if you want 1000 decimal place accuracy, it's the way to go! ie i've done 500!
|
|