Posts: 3,983
Threads: 178
Joined: Apr 2022
Reputation:
220
07-09-2023, 05:00 PM
As reported at the other forum:
Code: (Select All) Print (1D+17) * (1D+17) ' <<< the buggy one!
Print (1E+17) * (1E+17) ' E gets it right
The D notation is off by 1 power of 10.
b = b + ...
Posts: 422
Threads: 27
Joined: Apr 2022
Reputation:
26
07-09-2023, 05:53 PM
(This post was last modified: 07-09-2023, 05:55 PM by Jack.)
I remember Pete and I made some posts about it in the .org forum
besides the case you present, there were a number of anomalies, what does your example produce?
I get
9.999999999999999D+33 ' which is correct as far as floating-point goes, it's off by 1.0E-16
1E+34
note that I get this from my version, I modified the double-to-string and _float-to-string routines
Posts: 422
Threads: 27
Joined: Apr 2022
Reputation:
26
bplus, see what you get from the following
Code: (Select All)
Declare Library
Function snprintf& (Dest As String, Byval l As Long, frmt As String, Byval x As Double)
End Declare
Screen _NewImage(768, 768, 32)
_ScreenMove 0, 0
Cls
Locate 3, 1:
Color &HFF00FFFF~&&
Locate , 1: Print "c#";
Locate , 25: Print "c# + 1";
Print
Print
Color &HFFFF8000~&&
Print "c# = ... :": Color &HFFFFFFFF~&&
c# = 10#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 10000000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 100000000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
c# = 1000000000000000000000000000000#: Locate , 1: Print strf(c#);: Locate , 25: Print strf(c# + 1)
Print
Print
Function strf$ (x As Double)
Dim As String s
Dim As String frmt
Dim As Long l, ex, sign
sign = Sgn(x)
If sign < 0 Then x = -x
s = Spc(64)
frmt = "%.16g" + Chr$(0)
l = snprintf(s, Len(s), frmt, x)
s = _Trim$(s)
If InStr(s, ".") > 0 And Left$(s, 1) = "0" Then s = Mid$(s, 2)
If sign < 0 Then s = "-" + s Else s = " " + s
ex = InStr(s, "e")
If ex > 0 Then Mid$(s, ex, 1) = "F"
strf = s
End Function
Posts: 1,581
Threads: 59
Joined: Jul 2022
Reputation:
52
Try this in QBasic. If the output is the same then it stays fellas.
Posts: 303
Threads: 10
Joined: Apr 2022
Reputation:
44
(07-09-2023, 05:00 PM)bplus Wrote: As reported at the other forum:
Code: (Select All) Print (1D+17) * (1D+17) ' <<< the buggy one!
Print (1E+17) * (1E+17) ' E gets it right
The D notation is off by 1 power of 10. I'm pretty sure it's just a problem with rounding along with how the number is displayed. The floating point error for the double results in the value being slightly less than 1D+34, and because the value is slightly less it gets rounded to 1D+33 when displaying.
While I don't know what QBasic used to do. this seems like a bug since the number is still significantly closer to 1D+34 than 1D+33, so it should be displayed as that. I suspect it may be just rounding the mantissa without adjusting the exponent or something, I took a quick look at the code that renders the number but the issue wasn't clear to me. The way it works is pretty weird as it is, it might be easier to just redo it.
Posts: 2,698
Threads: 328
Joined: Apr 2022
Reputation:
218
Code: (Select All)
Dim a As Single, b As Double
For i = 1 To 20
a$ = "1D" + _Trim$(Str$(i))
b$ = "1E" + _Trim$(Str$(i))
a = Val(a$)
b = Val(b$)
Print a * a, b * b
Next
Run the above and watch what happens. No matter whether you like single (E) or double (E) values, they're all still floating point numbers and as such are *always* going to behave imperfectly due to the way the values get stored and processed in binary memory.
1E13 * 1E13 = 9.9999999E25..... whereas 1D13 * 1D13 = 1D26. <-- In this case, the 1D26 gives us the proper answer, while the 9.9999E25 is imprecise.
1D17 * 1D17 should probably give us 9.999999D33, as that's as close as it comes to calculating that value perfectly, but for whatever reason, the left is rounding to 1 (it's not truncating, as the answer then would be 9E33) and the right isn't incrementing to 34 as it ought to.
These values will never come out as perfectly precise as folks would like them to, but this does seem to be an issue with rounding screwing up somewhere in the "D" code.
Posts: 3,983
Threads: 178
Joined: Apr 2022
Reputation:
220
07-09-2023, 07:27 PM
(This post was last modified: 07-09-2023, 07:45 PM by bplus.)
Quote:1D17 * 1D17 should probably give us 9.999999D33
Right! that's about it with rounding errors, not almost 10 X's less that I am seeing. How does E do it with no rounding problems and correct exponent?
@matt
I tried the mantissa idea with 15 significant digits on the guy at the other forum and he didn't buy it, it's a bug and I think he's right because E works just fine.
@mnrvovrfc
It does work correctly in older QB according to the guy at other forum.
@jack yeah I am sure your code is likely correct! ;-))
b = b + ...
Posts: 422
Threads: 27
Joined: Apr 2022
Reputation:
26
@bplus
in the code I posted above, the doubles are converted to string using the snprintf function, please replace Print strf(c#) with Print c# and see what the output looks like
Posts: 3,983
Threads: 178
Joined: Apr 2022
Reputation:
220
07-10-2023, 12:42 AM
(This post was last modified: 07-10-2023, 12:51 AM by bplus.)
(07-09-2023, 10:40 PM)Jack Wrote: @bplus
in the code I posted above, the doubles are converted to string using the snprintf function, please replace Print strf(c#) with Print c# and see what the output looks like
@Jack I am missing the point you are trying to make?
BTW Print (1D+17) * (1D+17) ' <<< the buggy one! is coming out wrong at 1D+33 in case you didn't try it.
b = b + ...
Posts: 422
Threads: 27
Joined: Apr 2022
Reputation:
26
07-10-2023, 01:12 AM
(This post was last modified: 07-10-2023, 01:14 AM by Jack.)
bplus, the point was to show any buggy output by QB64 native double to string conversion as in your example Print (1D+17) * (1D+17)
as you can see in your output you have two 1D+22 and no 1D+23, also you have two 1D+28 and no 1D+29
using the C snprintf function would show them correctly
|