Compiler setting for accurate math?
#8
SOB code has me swearing, every time I think I have some accuracy in display settled, someone comes up with something to shake my faith.

@Pete 

Took me a long time to figure out what was going on, not pleasantly!

Here it is!
Code: (Select All)
For x = 100 To -.001 Step -.01

You (we) are (were) expecting x of a single type in the FOR loop to be better behaved than any other single type!

I have no idea why it decides not to round up at the 2 places in 10,000 numbers but look at those freak'n x values wandering as much as .005 off the expected value!

I did an equivalent test like yours dropping integers down: For cnt = 10000 to 1 step -1
only setting x = cnt/100 and x doesn't wander nearly as much as .005 and so roundDP$ returns expected results.

BTW Round2$ was old code that failed with negative numbers.

Code: (Select All)
$Console:Only
''test DP$ 2022-10-14  another Round Helper
'For n = 1 To 10000
'    If n = 7658 Then Beep: Flag = -1
'    a = n / 100
'    r$ = roundDP$(a, 2)
'    Print n, a, r$
'    If n Mod 20 = 0 Then
'        If Flag Then Sleep
'        Cls
'    End If
'Next


'Dim x ' ref Pete's test    https://staging.qb64phoenix.com/showthread.php?tid=1209&pid=10895#pid10895
'cnt = 10000
'For x = 100 To -.001 Step -.01
'    a$ = roundDP$(x, 2)
'    Print cnt, x;: Locate , 30: Print "Steve = "; a$
'    'Rem IF cnt <> VAL(MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)) THEN DO: WHILE _MOUSEINPUT: WEND: LOOP UNTIL _MOUSEBUTTON(1): _DELAY .1
'    'If Len(olda$) And Abs(Val(a$) - Val(olda$)) <> .01 Then Beep: Do: While _MouseInput: Wend: Loop Until _MouseButton(1): _Delay .1
'    If Len(olda$) And Abs(Val(a$) - Val(olda$)) <> .01 Then Beep: Sleep ' <<< b= mod this is less confusing than above
'    cnt = cnt - 1
'    olda$ = a$

'    'If cnt Mod 10 = 0 Then ' check screens
'    '    Sleep
'    '    Cls
'    'End If

'Next

Dim cnt As Long, x As Single
For cnt = 10000 To 5000 Step -1
    x = cnt / 100
    a$ = roundDP$(x, 2)
    Print cnt, x;: Locate , 30: Print "Steve = "; a$
    'Rem IF cnt <> VAL(MID$(a$, 1, INSTR(a$, ".") - 1) + MID$(a$, INSTR(a$, ".") + 1)) THEN DO: WHILE _MOUSEINPUT: WEND: LOOP UNTIL _MOUSEBUTTON(1): _DELAY .1
    'If Len(olda$) And Abs(Val(a$) - Val(olda$)) <> .01 Then Beep: Do: While _MouseInput: Wend: Loop Until _MouseButton(1): _Delay .1
    If Len(olda$) And Abs(Val(a$) - Val(olda$)) <> .01 Then Beep: Sleep ' <<< b= mod this is less confusing than above
    olda$ = a$

    'If cnt Mod 20 = 0 Then   ' check screens
    '    Sleep
    '    Cls
    'End If

Next



Function roundDP$ (num, digits) 'flaw if expontential notation involved.
    Print "roundDP recd this num"; num
    s$ = N2S$(Str$(num + Sgn(num) * (.5 * (10 ^ -digits))))
    dot = InStr(s$, ".")
    If dot Then r$ = Mid$(s$, 1, dot + digits) Else r$ = s$
    roundDP$ = r$
End Function

Function N2S$ (EXP$) 'remove scientific Notation to String (~40 LOC)
    'SMcNeill Jan 7, 2020 ref: https://www.qb64.org/forum/index.php?topic=1555.msg112989#msg112989
    'Last Function in code marked Best Answer (removed debug comments and blank lines added these 2 lines.)
    ReDim t$, sign$, l$, r$, r&&
    ReDim dp As Long, dm As Long, ep As Long, em As Long, check1 As Long, l As Long, i As Long
    t$ = LTrim$(RTrim$(EXP$))
    If Left$(t$, 1) = "-" Or Left$(t$, 1) = "N" Then sign$ = "-": t$ = Mid$(t$, 2)
    dp = InStr(t$, "D+"): dm = InStr(t$, "D-")
    ep = InStr(t$, "E+"): em = InStr(t$, "E-")
    check1 = Sgn(dp) + Sgn(dm) + Sgn(ep) + Sgn(em)
    If check1 < 1 Or check1 > 1 Then N2S = _Trim$(EXP$): Exit Function 'If no scientic notation is found, or if we find more than 1 type, it's not SN!
    Select Case l 'l now tells us where the SN starts at.
        Case Is < dp: l = dp
        Case Is < dm: l = dm
        Case Is < ep: l = ep
        Case Is < em: l = em
    End Select
    l$ = Left$(t$, l - 1) 'The left of the SN
    r$ = Mid$(t$, l + 1): r&& = Val(r$) 'The right of the SN, turned into a workable long
    If InStr(l$, ".") Then 'Location of the decimal, if any
        If r&& > 0 Then
            r&& = r&& - Len(l$) + 2
        Else
            r&& = r&& + 1
        End If
        l$ = Left$(l$, 1) + Mid$(l$, 3)
    End If
    Select Case r&&
        Case 0 'what the heck? We solved it already?
            'l$ = l$
        Case Is < 0
            For i = 1 To -r&&
                l$ = "0" + l$
            Next
            l$ = "." + l$
        Case Else
            For i = 1 To r&&
                l$ = l$ + "0"
            Next
            l$ = l$
    End Select
    N2S$ = sign$ + l$
End Function

I am glad I did do this because I am updating GUI for new dialogs in v3.4.1 and I was using the buggy Round2$ code that failed with neg numbers.

BTW I get something short of 5000 lines in Console, good to know.
b = b + ...
Reply


Messages In This Thread
RE: Compiler setting for accurate math? - by Jack - 11-30-2022, 11:48 PM
RE: Compiler setting for accurate math? - by Pete - 12-01-2022, 04:26 AM
RE: Compiler setting for accurate math? - by Pete - 12-01-2022, 10:43 AM
RE: Compiler setting for accurate math? - by bplus - 12-01-2022, 04:29 PM
RE: Compiler setting for accurate math? - by Pete - 12-01-2022, 04:52 PM
RE: Compiler setting for accurate math? - by Pete - 12-01-2022, 10:16 PM



Users browsing this thread: 4 Guest(s)