#MYCONST = BigNum <> ValD("#MYCONST")?

Just starting out? Need help? Post your questions and find answers here.
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

#MYCONST = BigNum <> ValD("#MYCONST")?

Post by skywalk »

I realize we need bignum lib's to perform arithmetic on very large numbers, but I was expecting a simple inequality to work if the numbers are within the DOUBLE and FLOAT ranges?
What

Code: Select all

; #MYCONST = BIGNUM <> ValD("#MYCONST")
; https://www.purebasic.fr/english/viewtopic.php?t=79180
#PB_MAX_Float       = 3.4028234663852886e38
#PB_MIN_Float       = 1.1754943508222875e-38      ; (normalized)
#PB_LOW_Float       = 1.4012984643248171e-45      ; (denormalized)
#PB_ESPILON_Float   = 1.1920928955078125e-7
#PB_MAX_Double      = 1.7976931348623157081e308
#PB_MIN_Double      = 2.2250738585072013831e-308  ; (normalized)
#PB_LOW_Double      = 4.9406564584124654418e-324  ; (denormalized)
#PB_EPSILON_Double  = 2.2204460492503130808e-16
#nNull              = -999.00000000000000000
#small1             = 1e-16       ; Epsilon value: small '1' to add to double calcs to round up or prevent overflows.
#small1_EQ          = 1e-9        ; Epsilon value: small '1' for IsEqual comparisons
;#TE_OVERFLOW        = 9.900000000000000000E37
;#TE_OVERFLOW        = ValD("9.9e37") = 98999999999999993000000000000000000000.0
#TE_OVERFLOW        = 98999999999999993e21;000000000000000000000.0
Macro IsEqual(x, y, small1=#small1_EQ)
  Bool(Abs((x)-(y)) <= small1)
EndMacro
;-{ TEST
Structure TD
  i.i
  x.d
EndStructure
Procedure.i isOVERFLOW_REAL(r$, *d.TD)  ;-! Simulate function acting on very large number
  *d\x = ValD(r$)
  If *d\x >= #TE_OVERFLOW ;9.9+37
    *d\x = #nNull
    ProcedureReturn 1
  Else
    ProcedureReturn 0
  EndIf
EndProcedure
Procedure.i isOVERFLOW_REALeq(r$, *d.TD)  ;-! Simulate function acting on very large number
  *d\x = ValD(r$)
  If IsEqual(*d\x, #TE_OVERFLOW);9.9+37
    *d\x = #nNull
    ProcedureReturn 1
  Else
    ProcedureReturn 0
  EndIf
EndProcedure
Global r.TD, r2.TD, r3.TD
Global.i rs = 24
Global r$, TEO$ = "9.900000000000000000E37"
;-! Case 1: Overflow inequalities
r$ = "9.9e+37"
Debug "Case 1: isOverflow? " + r$ + " >= " + TEO$ + " FAIL."
Debug "Case 1: isOverflow should be 1."
Debug "Case 1: REAL Overflow -> " + Str(isOVERFLOW_REAL(r$, @r))
Debug "Case 1: REAL Overflow~-> " + Str(isOVERFLOW_REALeq(r$, @r))
Debug "~~~"
r$ = "9.9e+36"
Debug "Case 2: isOverflow? " + r$ + " >= " + TEO$ + " OK."
Debug "Case 2: isOverflow should be 0."
Debug "Case 2: REAL Overflow -> " + Str(isOVERFLOW_REAL(r$, @r))
Debug "Case 2: REAL Overflow~-> " + Str(isOVERFLOW_REALeq(r$, @r))
Debug "~~~"
r$ = "9.9e+3"
Debug "Case 3: isOverflow? " + r$ + " >= " + TEO$ + " OK."
Debug "Case 3: isOverflow should be 0."
Debug "Case 3: REAL Overflow -> " + Str(isOVERFLOW_REAL(r$, @r))
Debug "Case 3: REAL Overflow~-> " + Str(isOVERFLOW_REALeq(r$, @r))
Debug "~~~"
r$ = "9.9e+37"
r\x  = 9.9e37
r2\x = 9.9000000000000000000e37
Debug "Case 4: Large Diff? (" + r$ + " - " + TEO$ + ") OK."  ;-! Case 4: Large Diff
Debug "r    = " + LSet(StrD(r\x,16),rs+16)
Debug "r2   = " + LSet(StrD(r2\x,16),rs+16)
Debug "r-r2 = " + LSet(StrD(r\x - r2\x,16),rs)
Debug "~~~"
#SOMECONST = 9.9e21
r$ = StrD(9.9e21,16)
r2$ = StrD(#SOMECONST,16)
Debug "Case 4: Small Diff? (" + r$ + " - " + r2$ + ") OK."  ;-! Case 4: Small Diff
Debug "r    = " + LSet(StrD(r\x,16),rs+16)
Debug "r2   = " + LSet(StrD(r2\x,16),rs+16)
Debug "r-r2 = " + LSet(StrD(r\x - r2\x,16),rs)
Debug "~~~ DONE ~~~"
#MY_CONST = 9.9e37
r$ = "9.9e37"
Debug "9.9e37   = " + LSet(StrD(ValD(r$),16),rs)
Debug "#9.9e37  = " + LSet(StrD(#MY_CONST,16),rs)
Debug "DIFF     = " + LSet(StrD(ValD(r$) - #MY_CONST,16),rs)
;-} TEST
EDIT: Thanks to STARGATE for showing me #TE_OVERFLOW <> ValD(#TE_OVERFLOW)
Last edited by skywalk on Wed May 18, 2022 3:35 pm, edited 2 times in total.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
jack
Addict
Addict
Posts: 1336
Joined: Fri Apr 25, 2003 11:10 pm

Re: BigNum<=Max Float value comparisons fail?

Post by jack »

I wrote a simple decimal floating-point library but at present it's written in another basic, if there's interest then I may translate it to PB
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: BigNum<=Max Float value comparisons fail?

Post by mk-soft »

Only a certain number of digits fit into float or double. Thus, with float 1 billion plus 1 is still 1 billion.

It is therefore always relevant to calculate only in a range that also fits together.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: BigNum<=Max Float value comparisons fail?

Post by STARGÅTE »

What do you want to show us with your code, skywalk?
It looks very messy.
Why all these constants, which are not used?
Why switching from float to double to string to pointer ...?
What is "#TE_OVERFLOW" ?
What a mess.

Just a note: You can not compare "Abs((x)-(y)) <= #small1_EQ" with #small1_EQ = 1e-9, but x and y are large, because doubles just have 15 precise digits. What you can do, is a relative comparison:

Code: Select all

Abs((X)-(Y)) / (Abs(X)+Abs(Y))  < 1e-9
I can also recomment my Library: Lizard - Script language for symbolic calculations, arbitrary large and precise numbers and more
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: BigNum<=Max Float value comparisons fail?

Post by skywalk »

No mess, I list the constants to show the range of numbers allowed. But clearly, it is not enough for a comparison between 2 numbers anywhere within those ranges.
The TE_OVERFLOW constant is just 1 such number I must compare in my system. Anything >= than that is overflow.

The macro just has a default 1e-9.
I set it to 1e37 in the big compare.

I was trying to avoid a bignum lib for >=.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: BigNum<=Max Float value comparisons fail?

Post by STARGÅTE »

Ok, then let me ask again, what is the issue? The line with "FAIL"?

Here you convert r$ = "9.9e+37" into a double, which is 98999999999999993000000000000000000000.0.
This number is smaller than #TE_OVERFLOW, which is 99000000000000012000000000000000000000.0.
This means no overflow, the output is correct.
But because of your IsEqual macro with 1e37, both numbers are equal.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: BigNum<=Max Float value comparisons fail?

Post by skywalk »

Yes! Now you get it.
The #TE_OVERFLOW value is different than the string equivalent using ValD().
STARGÅTE wrote: Wed May 18, 2022 6:45 am Here you convert r$ = "9.9e+37" into a double, which is 98999999999999993000000000000000000000.0
This number is smaller than #TE_OVERFLOW, which is 99000000000000012000000000000000000000.0 :)
Thanks for this!
I assumed that #constant = some-typed-number == ValD("same-typed-number") :shock: :evil:
I will reduce #TE_OVERFLOW to the ValD() equivalent.
Now everything works. :)
And I changed the topic to match this.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply