Τετάρτη 4 Ιουλίου 2018

Αναθεώρηση 18 (Έκδοση 9.3) - Εύρεση PI

Διορθώθηκαν τρια λάθη. Παράλληλα βάζω παραδείγματα εδώ:  (δείτε στο τέλος της σελίδας συνδέσεις προς κάθε παράδειγμα).

Παρακάτω είναι ένας τρόπος υπολογισμού της σταθεράς π  (S. Rabinowitz), δίνοντας τον αριθμό δεκαδικών που επιθυμούμε. Είναι γραμμένο με αγγλικές εντολές, αλλά εύκολα γράφεται με ελληνικές. (Η Μ2000 έχει δυο σετ εντολών, στα Αγγλικά και στα Ελληνικά - και μπορούμε να έχουμε μείξη αυτών, αλλά όχι σε μια εντολή, εκτός από εκφράσεις όπου εκεί μπορούν να συνυπάρχουν συναρτήσεις στα ελληνικά και στα αγγλικά)



Σχετικά Ο Κόσμος του π   και  Spigot Algorithm
 

Module FindPi(Digits){
      Digits++
      n=Int(3.32*Digits)
      PlusOne=Lambda N=0% -> {
            =N
            N++
      }
      PlusTwo=Lambda N=1% -> {
            =N
            N+=2
      }
      Dim A(n)<<PlusOne(), B(n)<<PlusTwo()
      Dim Ten(n), CarrierOver(n), Sum(n),Remainder(n)=2
      Predigits=Stack
      CallBack=lambda fl=true, Chars=0 (x)->{
            Print x;
            Chars++
            If fl then Print "." : Print " "; : fl=false : Chars=0 : exit
            If Chars=50 then {
                  Print
                  Print " ";
                  Chars=0
            } else.if (Chars mod 5)=0 then {
                   Print " ";
            }
      }
      Print "Pi=";
      Digits++
      While Digits {
            NextDigit(&CallBack)
            Digits--
      }
      print

      Sub NextDigit(&f)
          CarrierOver=0
            For k=n-1 to 1 {
            Ten(k)=Remainder(k)*10%
            CarrierOver(k)=CarrierOver
            Sum(k)=Ten(k)+CarrierOver(k)
            q=Sum(k) div B(k)
            Remainder(k)=Sum(k)-B(k)*q
            CarrierOver=A(k)*q
            }
            Ten(0)=Remainder(0)*10%
            CarrierOver(0)=CarrierOver
            Sum(0)=Ten(0)+CarrierOver(0)
            q=Sum(0) div 10%
            Remainder(0)=Sum(0)-10%*q
            if q<>9 and q<>10 then {
                  Stack Predigits {
                        While not empty {
                              Call f(Number)
                        }      
                        Push q
                  }       
            } else.if q=9 Then {
                  Stack Predigits { Data q }
            } else {
                  Stack Predigits {
                  While not empty {
                        Call f((Number+1) mod 10)
                  }      
                  Push 0
                  }
            }
      End Sub
}
FindPi 200

Προχωρημένο! Δείνει επακριβώς τον αριθμό δεκαδικών που ζητάμε. Ο έλεγχος γίνεται στην εμφάνιση των δεκαδικών. Τρέχει γρηγορότερα, γιατί γίνεται ανανέωση της φόρμας της κονσόλας όποτε θέλουμε με την Refresh (Ανανέωση), ενώ έχουμε ορίσει να γίνονται αυτόματα να παίρνει λιγότερες φορές τον έλεγχο το λειτουργικό σύστημα. Ελληνικά η εντολή είναι Θέσε Γρήγορα ! από γραμμή μέσα σε τμήμα, ενώ εκτός, στην κοσνόλα είναι Γρήγορα !
Μειώσαμε και το πότε θα "ακούει" το πληκτρολόγιο ο διερμηνευτής. Εδώ γίνεται όταν κάνουμε Ανανέωση.

Advanced. We get exactly the digits we want. Run faster handling execution slice time (using less window refreshes)


Module Checkpi {
      Module FindPi(Digits){
            Digits++
            n=Int(3.32*Digits)
            PlusOne=Lambda N=0% -> {
                  =N
                  N++
            }
            PlusTwo=Lambda N=1% -> {
                  =N
                  N+=2
            }
            Dim A(n)<<PlusOne(), B(n)<<PlusTwo()
            Dim Ten(n), CarrierOver(n), Sum(n),Remainder(n)=2
            OutPutDigits=Digits
            Predigits=Stack
            CallBack=lambda fl=true, Chars=0 (x)->{
                  Print x;
                  Chars++
                  If fl then Print "." : Print " "; : fl=false : Chars=0 : exit
                  If Chars=50 then {
                        Print
                        Print " ";
                        Chars=0
                        Refresh
                  } else.if (Chars mod 5)=0 then {
                         Print " ";
                         Refresh
                  }
                  \\ explicitly refresh output layer, using Fast ! mode of speed
            }
            Print "Pi=";
             While Digits {
                  NextDigit(&CallBack, &Digits)
            }
            print
            Refresh
            Sub NextDigit(&f, &D)
                CarrierOver=0
                  For k=n-1 to 1 {
                  Ten(k)=Remainder(k)*10%
                  CarrierOver(k)=CarrierOver
                  Sum(k)=Ten(k)+CarrierOver(k)
                  q=Sum(k) div B(k)
                  Remainder(k)=Sum(k)-B(k)*q
                  CarrierOver=A(k)*q
                  }
                  Ten(0)=Remainder(0)*10%
                  CarrierOver(0)=CarrierOver
                  Sum(0)=Ten(0)+CarrierOver(0)
                  q=Sum(0) div 10%
                  Remainder(0)=Sum(0)-10%*q
                  if q<>9 and q<>10 then {
                        Stack Predigits {
                              While not empty {
                                Call f(Number)
                                if D>0 then D--
                                If D=0 then flush ' empty stack
                              }      
                              Push q
                        }       
                  } else.if q=9 Then {
                        Stack Predigits { Data q }
                  } else {
                        Stack Predigits {
                        While not empty {
                              Call f((Number+1) mod 10)
                              if D>0 then D--
                              If D=0 then flush ' empty stack
                        }      
                        Push 0
                        }
                  }
            End Sub
      }
      \\ reduce time to share with OS
      \\ Need explicitly use of refresh output layer (M2000 console)
      \\ Slow for a screen refresh per statement and give more time to OS
      Rem Set Slow
      \\ Fast is normal screen refresh, per Refresh time, and give standrard time to OS
      Rem Set Fast
      \\ Fast ! use Refresh for screen refresh, and give less time o OS than standard
      \\ Esc key work when Refresh executed (and OS get little time)
      Set Fast !
      FindPi 4
      FindPi 28
      Print Pi ' pi in M2000 is Decimal type with 28 digits (1plus 28 after dot, is same as FindPi 28)
      Refresh
      FindPi 50
}
Flush ' empty stack of values
CheckPi
List  ' no variables exist
Modules ? ' current module exist
Stack ' Stack of values  ' has to be empty

Έκδοση χωρίς υπορουτίνα, με χρήση ακεραίων 16bit (version without sub, more compact, using integer 16bit) (2 Mar 2022)

Form 80, 32
Module Checkpi {
Module FindPi (D as integer){
Def integer k, q, n
D++:n=Int(3.32*D)
PlusOne=Lambda N=0% -> {=N:N++}
PlusTwo=Lambda N=1% -> {=N:N+=2%}
Dim A(n)<<PlusOne(), B(n)<<PlusTwo()
Dim Ten(n), CarrierOver(n), Sum(n), Remainder(n)=2%
OutPutDigits=D
Predigits=Stack
f=lambda fl=true, Chars=0% (x)->{
Print x;
Chars++
If fl then Print "." : Print " "; : fl=false : Chars=0% : exit
If Chars=50% then
Print :Print " "; :Chars=0% : Refresh
else.if Chars mod 5%=0% then
Print " ";
Refresh
end if
}
Print "Pi=";
While D
CarrierOver=0%
For k=n-1 to 1
Ten(k)=Remainder(k)*10%
CarrierOver(k)=CarrierOver
Sum(k)=Ten(k)+CarrierOver(k)
q=Sum(k) div B(k)
Remainder(k)=Sum(k)-B(k)*q
CarrierOver=A(k)*q
Next
Ten(0)=Remainder(0)*10%
CarrierOver(0)=CarrierOver
Sum(0)=Ten(0)+CarrierOver(0)
q=Sum(0) div 10%
Remainder(0)=Sum(0)-10%*q
if q<>9% and q<>10% then
Stack Predigits {
While not empty
Call f(Number)
if D>0% then D--
If D=0% then flush ' empty stack
End While
Push q
}
else.if q=9% Then
Stack Predigits { Data q }
else
Stack Predigits {
While not empty
Call f((Number+1) mod 10%)
if D>0% then D--
If D=0% then flush ' empty stack
End While
Push 0%
}
end if
End While
print
Refresh
}
Set Fast !
FindPi 4
FindPi 28
Print Pi
Refresh
FindPi 500
Set Fast
}
Flush
CheckPi



Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.