Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
D notation bug
#1
Bug 
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 + ...
Reply
#2
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
Reply
#3
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
Reply
#4
Try this in QBasic. If the output is the same then it stays fellas.
Reply
#5
(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.
Reply
#6
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.
Reply
#7
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 + ...
Reply
#8
@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
Reply
#9
(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 + ...
Reply
#10
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
Reply




Users browsing this thread: 1 Guest(s)