Author Topic: Maths accuracy  (Read 8488 times)

0 Members and 1 Guest are viewing this topic.

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: Maths accuracy
« Reply #30 on: May 27, 2021, 12:27:40 pm »
1.2 ^ 3.5 = 1.2 ^ (35/10) does this get us closer?
1.2^3.5=1.2^3*sqr(1.2)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Maths accuracy
« Reply #31 on: May 27, 2021, 12:40:52 pm »
1.2^3.5=1.2^3*sqr(1.2)

Ah yes, that is a hint as to how I do powers (of real numbers not just integers) by converting to binary and then using sqr(2) and half of that and half of that...

Oh it's Sqr of Sqr(2) and on and on... (not half of half of half ...  but sqr(sqr(Sqr(2)))...)
Code: QB64: [Select]
  1. _Title "Power Function by bplus"
  2. 'QB64 X 64 version 1.2 20180228/86  from git b301f92
  3.  
  4. ' started 2018-07-23  Naalaa has no power function (or operator), so I wrote a power function for it.
  5. ' ''Power pack the short version.txt
  6. ' ''written for Naalaa 6 by bplus posted 2018-07-23
  7. ' ''extracted from large test of fractions, random number functions, string... in Power test.txt
  8.  
  9. ' OMG the crazy thing worked! It produced decent estimates of roots given the limitations of precision...
  10. ' Now I want to see how well it works with far greater precision available. So here we are, looking to see
  11. ' how this function compares to the regualar ^ operator in QB64.
  12.  
  13. 'from Naalaa comments:
  14. ' The main purpose of this code: to demo a power function for real numbers,
  15.  
  16. ' I had an idea for how real numbers to the power of real numbers might be done ie x ^ y = ?
  17. ' This means that not only can you take SQR of a number, you can get cube or cube root, quartic, 5th 6th... roots and any multiple
  18.  
  19. ' It came from this simple idea
  20. ' 2 ^ 3.5 = 2 ^ 3 * 2 ^ .5 = 8 * Sqr(2)
  21. ' 3 ^ 3.5 = 3 ^ 3 * 3 ^ .5 = 27 * Sqr(3)
  22.  
  23. ' so 2 ^ 3.25 = 2 ^ 3 * 2 ^ .25
  24. ' what is 2 ^ .25 ?  It is sqr(sqr(2)) !
  25.  
  26. ' likewise 2 ^ 3.125 = 2 ^ 3 * 2 ^ 1/8
  27. ' what is 2 ^ 1/8 ? It is sqr(sqr(sqr(2))) !
  28.  
  29. ' any decimal can be written as a sum of fraction powers of 2 ie 1/2^n, as any integer can be written in powers of 2.
  30. ' in binary expansions
  31. ' 1/2 = .1       or .5 base 10
  32. ' 1/4 = .01      or .25 base 10
  33. ' 1/8 = .001     or .125 base 10
  34. ' 1/16 = .0001   or .0625 base 10
  35.  
  36. ' So with binary expansion of decimal, we can SQR and multiply our way to an estimate
  37. ' of any real number to the power of another real number using binary expansion of
  38. ' the decimal parts as long as we stay in Naalaa integer limits and are mindful of precision.
  39.  
  40. Const wW = 800
  41. Const wH = 600
  42. Screen _NewImage(wW, wH, 32)
  43. _ScreenMove 360, 60
  44.  
  45.     Print "Testing the power(x, pow) function:"
  46.     Input "(nothing) quits, Please enter a real number to raise to some power. x = "; x
  47.     If x = 0 Then Exit Do
  48.     Input "(nothing) quits, Please enter a real number for the power. pow = ", pw
  49.     If pw = 0 Then Exit Do
  50.     result = power(x, pw)
  51.     Print result; " is what we estimate for"; x; " raised to power of"; pw
  52.     Print x ^ pw; " is what the ^ operator gives us."
  53.     Print
  54. Print "Far from precise of course, but this code is clear proof of concept!"
  55. Print " OMG, it worked!!!"
  56.  
  57.  
  58. ' A power function for real numbers (small ones but still!)
  59. ' x to the power of pow
  60. Function power## (x As _Float, pow As _Float)
  61.     'this sub needs 2 other subs
  62.     'bExpand20$
  63.     'split though for this split is overkill
  64.     Dim build As _Float
  65.     ReDim s(0) As String
  66.     r$ = "0" + Str$(pow) 'in case pow starts with decimal
  67.     Split s$(), r$, "."
  68.     integer$ = s$(0)
  69.     build = 1.0
  70.     If integer$ <> "0" Then
  71.         p = Val(integer$)
  72.         For i = 1 To p
  73.             build = build * x
  74.         Next
  75.     End If
  76.     If UBound(s$) = 0 Then power = build: Exit Function
  77.     'that takes care of integer part,
  78.     'now for the fraction part convert decimal to fraction
  79.     n$ = s$(1)
  80.     ld = Len(n$)
  81.     While Right$(n$, 1) = "0"
  82.         n$ = Left$(n$, ld - 1)
  83.         ld = Len(n$)
  84.     Wend
  85.     denom& = 10
  86.     For i = 2 To ld
  87.         denom& = denom& * 10
  88.     Next
  89.     numer& = Val(n$)
  90.     'OK for bExpand20$ don't have to simplify and that saves us having to extract n and d again from n/d
  91.     bs$ = bExpand60$(numer&, denom&)
  92.     'at moment we haven't taken any sqr of x
  93.     runningXSQR = x
  94.     'run through all the 0's and 1's in the bianry expansion of the fraction part of the power float
  95.     For i = 1 To Len(bs$)
  96.         'this is the matching sqr of the sqr of the sqr... of x
  97.         runningXSQR = Sqr(runningXSQR)
  98.         'for every 1 in the expansion, multiple our build with the running sqr of ... sqr of x
  99.         If Mid$(bs$, i, 1) = "1" Then build = build * runningXSQR
  100.     Next
  101.     'our build should be a estimate or x to power of pow
  102.     power = build
  103.  
  104. 'write a series of 1s and 0s that represent the decimal fraction n/d in binary 60 places long
  105. Function bExpand60$ (nOver&, d&)
  106.     Dim b As _Float, r As _Float
  107.     ' b for base
  108.     b = 0.5
  109.     ' r for remainder
  110.     r = nOver& / d&
  111.     ' s for string$ 0's and 1's that we will build and return for function value
  112.     s$ = ""
  113.     ' f for flag to stop
  114.     f% = 0
  115.     ' c for count to track how far we are, don't want to go past 20
  116.     c% = 0
  117.     While f% = 0
  118.         If r < b Then
  119.             s$ = s$ + "0"
  120.         Else
  121.             s$ = s$ + "1"
  122.             If r > b Then
  123.                 r = r - b
  124.             Else
  125.                 f% = 1
  126.             End If
  127.         End If
  128.         c% = c% + 1
  129.         If c% >= 60 Then f% = 1
  130.         b = b * 0.5
  131.     Wend
  132.     bExpand60$ = s$
  133.  
  134. Sub Split (arr() As String, mystr As String, delim As String)
  135.     Dim c As String * 1, curpos As Long, arrpos As Long, le As Long
  136.     curpos = 1: arrpos = 0
  137.     le = Len(mystr)
  138.     Do Until (curpos > le)
  139.         c = Mid$(mystr, curpos, 1) ' Get 1 ctr
  140.         If (c <> delim) Then
  141.             arr(arrpos) = arr(arrpos) + c
  142.         Else
  143.             arrpos = arrpos + 1
  144.             ReDim _Preserve arr(arrpos + 1) As String 'AS STRING required or it assumes the default type which is SINGLE
  145.         End If
  146.         curpos = curpos + 1
  147.     Loop
  148.     ReDim _Preserve arr(arrpos) As String
  149.  
  150.  
  151.  
  152.  

Now all I need to do is covert it to string math functions ;-))
« Last Edit: May 27, 2021, 12:46:36 pm by bplus »

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Maths accuracy
« Reply #32 on: May 27, 2021, 01:12:48 pm »
Passing power to root can be used to get your result or if you don’t have a whole solution, to express the result as a root.

For example, using my n'th root function, you could solve 1,2^3.5 as:

X = 10th root of 1.2^35, which = 1.2^3.5. (Answer is 1.892929159)

1.2 becomes the radicando (root content), 10 becomes the root index and 35 remains as exponent of 1.2

Passing power to root can be used to get your result.

Just spitballing, but if you Check for the y in x^y not = to its modulus will tell the function it needs to calculate the power using the root.

I will try and code that for your Math Regulator program.

George


Hmm...

Like I said a ^ b where b is integer, I get that though god help us if that integer is huge ;-))

But if b were float?

What if I mult b by 10 until it is all integer? mult a (b  * 10 ^ Integer times) then what? divide by some log of 10 Integer times? Yeah, nah... ;-))

1.2 ^ 3.5 = 1.2 ^ (35/10) does this get us closer?
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Maths accuracy
« Reply #33 on: June 12, 2021, 10:29:53 pm »
hi @JohnUKresults.  I'm very late to the party with this, but here's another workaround if you're interested (you asked if there is another).  Since PRINT USING returns correct results you want, here's a way to convert/return a PRINT USING output as a variable, by reading a second screen output.  It's no better, but just shows another way, mostly that it’s possible to get PRINT USING output as a variable.

- Dav

Code: QB64: [Select]
  1. finishseconds! = 39818.38
  2. startseconds! = 34200.77
  3.  
  4. PRINT finishseconds! - startseconds!
  5. PRINT USING "#####.##"; finishseconds! - startseconds!
  6. r = PU2(finishseconds! - startseconds!)
  7.  
  8. FUNCTION PU2 (math)
  9.     'returns a print using readout as a variable
  10.     org& = _DEST 'save current screen
  11.     pun& = _NEWIMAGE(600, 100, 256) 'make new one
  12.     _DEST pun& 'switch to it
  13.     _SOURCE pun&
  14.     PRINT USING "#############.##"; math 'do the deed
  15.     FOR x = 1 TO 30 'read chracters off screen
  16.         n$ = n$ + CHR$(SCREEN(1, x, 0))
  17.     NEXT
  18.     n$ = LTRIM$(RTRIM$(n$)) 'remove any spaces
  19.     _DEST org& 'switch back to original screen
  20.     _SOURCE org&
  21.     PU2 = VAL(n$) 'return variable
  22.  

 
« Last Edit: June 12, 2021, 11:00:36 pm by Dav »

Offline JohnUKresults

  • Newbie
  • Posts: 40
    • View Profile
Re: Maths accuracy
« Reply #34 on: June 14, 2021, 09:25:05 am »
Hi Dav

Thanks for that suggestion.

However, it's the calculation which is important, not the display of the result, so I will have to stick with multiplying the time to make an integer, doing the subtraction, and then putting the decimal point back into the right place for the results.

Like your idea though - might be useful for something else!