performance - نسبي - من هو مكتشف الباي




ما هي أسرع طريقة للحصول على قيمة π؟ (16)

حساب PI في وقت الترجمة مع D.

(تم نسخها من DSource.org )

/** Calculate pi at compile time
 *
 * Compile with dmd -c pi.d
 */
module calcpi;

import meta.math;
import meta.conv;

/** real evaluateSeries!(real x, real metafunction!(real y, int n) term)
 *
 * Evaluate a power series at compile time.
 *
 * Given a metafunction of the form
 *  real term!(real y, int n),
 * which gives the nth term of a convergent series at the point y
 * (where the first term is n==1), and a real number x,
 * this metafunction calculates the infinite sum at the point x
 * by adding terms until the sum doesn't change any more.
 */
template evaluateSeries(real x, alias term, int n=1, real sumsofar=0.0)
{
  static if (n>1 && sumsofar == sumsofar + term!(x, n+1)) {
     const real evaluateSeries = sumsofar;
  } else {
     const real evaluateSeries = evaluateSeries!(x, term, n+1, sumsofar + term!(x, n));
  }
}

/*** Calculate atan(x) at compile time.
 *
 * Uses the Maclaurin formula
 *  atan(z) = z - z^3/3 + Z^5/5 - Z^7/7 + ...
 */
template atan(real z)
{
    const real atan = evaluateSeries!(z, atanTerm);
}

template atanTerm(real x, int n)
{
    const real atanTerm =  (n & 1 ? 1 : -1) * pow!(x, 2*n-1)/(2*n-1);
}

/// Machin's formula for pi
/// pi/4 = 4 atan(1/5) - atan(1/239).
pragma(msg, "PI = " ~ fcvt!(4.0 * (4*atan!(1/5.0) - atan!(1/239.0))) );

أنا أبحث عن أسرع طريقة للحصول على قيمة π ، كتحدي شخصي. بشكل أكثر تحديدًا ، أنا أستخدم طرقًا لا تتضمن استخدام #define الثوابت مثل M_PI ، أو ترميز الرقم في الثابت.

يختبر البرنامج أدناه الطرق المختلفة التي أعرفها. نسخة التجميع المضمنة هي ، من الناحية النظرية ، أسرع الخيارات ، على الرغم من أنها غير محمولة بوضوح. لقد قمت بتضمينها كخط أساسي للمقارنة مع الإصدارات الأخرى. في اختباراتي ، مع الإضافات المدمجة ، يكون الإصدار 4 * atan(1) الأسرع على الإصدار 4.2 من GCC ، لأنه يقوم تلقائيًا atan(1) في ثابت. مع -fno-builtin المحدد ، فإن إصدار atan2(0, -1) هو الأسرع.

إليك برنامج الاختبار الرئيسي ( pitimes.c ):

#include <math.h>
#include <stdio.h>
#include <time.h>

#define ITERS 10000000
#define TESTWITH(x) {                                                       \
    diff = 0.0;                                                             \
    time1 = clock();                                                        \
    for (i = 0; i < ITERS; ++i)                                             \
        diff += (x) - M_PI;                                                 \
    time2 = clock();                                                        \
    printf("%s\t=> %e, time => %f\n", #x, diff, diffclock(time2, time1));   \
}

static inline double
diffclock(clock_t time1, clock_t time0)
{
    return (double) (time1 - time0) / CLOCKS_PER_SEC;
}

int
main()
{
    int i;
    clock_t time1, time2;
    double diff;

    /* Warmup. The atan2 case catches GCC's atan folding (which would
     * optimise the ``4 * atan(1) - M_PI'' to a no-op), if -fno-builtin
     * is not used. */
    TESTWITH(4 * atan(1))
    TESTWITH(4 * atan2(1, 1))

#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__))
    extern double fldpi();
    TESTWITH(fldpi())
#endif

    /* Actual tests start here. */
    TESTWITH(atan2(0, -1))
    TESTWITH(acos(-1))
    TESTWITH(2 * asin(1))
    TESTWITH(4 * atan2(1, 1))
    TESTWITH(4 * atan(1))

    return 0;
}

fldpi.c التجميع المضمّنة ( fldpi.c ) التي ستعمل فقط لأنظمة x86 و x64:

double
fldpi()
{
    double pi;
    asm("fldpi" : "=t" (pi));
    return pi;
}

ونص بناء يبني جميع التكوينات التي build.sh ( build.sh ):

#!/bin/sh
gcc -O3 -Wall -c           -m32 -o fldpi-32.o fldpi.c
gcc -O3 -Wall -c           -m64 -o fldpi-64.o fldpi.c

gcc -O3 -Wall -ffast-math  -m32 -o pitimes1-32 pitimes.c fldpi-32.o
gcc -O3 -Wall              -m32 -o pitimes2-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -fno-builtin -m32 -o pitimes3-32 pitimes.c fldpi-32.o -lm
gcc -O3 -Wall -ffast-math  -m64 -o pitimes1-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall              -m64 -o pitimes2-64 pitimes.c fldpi-64.o -lm
gcc -O3 -Wall -fno-builtin -m64 -o pitimes3-64 pitimes.c fldpi-64.o -lm

بصرف النظر عن الاختبار بين أعلام المترجم المختلفة (لقد قارنت 32 بت مع 64 بت أيضًا لأن التحسينات مختلفة) ، فقد حاولت أيضًا تبديل ترتيب الاختبارات حولها. ولكن لا يزال ، إصدار atan2(0, -1) لا يزال يظهر في المقدمة في كل مرة.


نهج أفضل

للحصول على إخراج الثوابت القياسية مثل pi أو المفاهيم القياسية ، يجب أن نذهب أولاً إلى الأساليب المضمنة المتوفرة للغة التي تستخدمها. سيعود القيمة في أسرع طريقة وأفضل طريقة أيضًا. أنا أستخدم الثعبان للحصول على أسرع طريقة للحصول على قيمة بي

  • بي متغير من مكتبة الرياضيات . مكتبة الرياضيات تخزين المتغير بي ثابت.

math_pi.py

import math
print math.pi

قم بتشغيل البرنامج النصي باستخدام أداة الوقت الخاصة بـ linux /usr/bin/time -v python math_pi.py

انتاج:

Command being timed: "python math_pi.py"
User time (seconds): 0.01
System time (seconds): 0.01
Percent of CPU this job got: 91%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.03
  • استخدام قوس كوس طريقة الرياضيات

acos_pi.py

import math
print math.acos(-1)

تشغيل البرنامج النصي مع فائدة الوقت من لينكس /usr/bin/time -v python acos_pi.py

انتاج:

Command being timed: "python acos_pi.py"
User time (seconds): 0.02
System time (seconds): 0.01
Percent of CPU this job got: 94%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.03

bbp_pi.py

from decimal import Decimal, getcontext
getcontext().prec=100
print sum(1/Decimal(16)**k * 
          (Decimal(4)/(8*k+1) - 
           Decimal(2)/(8*k+4) - 
           Decimal(1)/(8*k+5) -
           Decimal(1)/(8*k+6)) for k in range(100))

تشغيل البرنامج النصي مع فائدة الوقت من لينكس /usr/bin/time -v python bbp_pi.py

انتاج:

Command being timed: "python c.py"
User time (seconds): 0.05
System time (seconds): 0.01
Percent of CPU this job got: 98%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.06

أفضل طريقة لذلك هي استخدام طريقة المضمنة المقدمة من اللغة لأنها الأسرع والأفضل للحصول على الإخراج. في الثعبان استخدام math.pi


إذا كنت ترغب في حساب تقريبي لقيمة π (لسبب ما) ، يجب عليك تجربة خوارزمية استخراج ثنائية. تحسين Bellard لـ BBP يعطي PI في O (N ^ 2).

إذا كنت ترغب في الحصول على تقدير تقريبي لقيمة π لإجراء الحسابات ، فقم بما يلي:

PI = 3.141592654

منحت ، هذا مجرد تقريب ، وليس دقيقًا تمامًا. إنه خارج بأكثر من 0.00000000004102. (أربعة عشرة تريليونات ، حوالي 4 / 10،000،000،000 ).

إذا كنت تريد إجراء الرياضيات باستخدام π ، فاحصل على قلم رصاص وورقة أو حزمة جبر كمبيوتر ، واستخدم القيمة الدقيقة π.

إذا كنت تريد حقًا صيغة ، فهذه الصيغة ممتعة:

π = - i ln (-1)


إذا كنت تعني الأسرع لكتابة الرمز ، golfscript حل golfscript :

;''6666,-2%{2+.2/@*\/10.3??2*+}*`1000<~\;

إليك وصفًا عامًا لتقنية لحساب pi التي تعلمتها في المدرسة الثانوية.

أنا أشارك هذا فقط لأنني أعتقد أن الأمر بسيط بما فيه الكفاية بحيث يمكن لأي شخص أن يتذكره ، إلى أجل غير مسمى ، بالإضافة إلى أنه يعلمك مفهوم أساليب "مونت كارلو" - وهي طرق إحصائية للوصول إلى الإجابات التي لا يبدو أنها على الفور استنتاجي من خلال عمليات عشوائية.

ارسم مربعًا وأدرج ربعًا (ربع نصف دائرة) داخل ذلك المربع (رباع نصف قطره يساوي جانب المربع ، بحيث يملأ أكبر قدر ممكن من المربع)

الآن ، يمكنك رمي لعبة رمي السهام في المربع ، وتسجيل المكان الذي تهبط فيه - أي ، اختر نقطة عشوائية في أي مكان داخل المربع. بالطبع ، سقطت داخل الساحة ، لكن هل هي داخل نصف الدائرة؟ سجل هذه الحقيقة.

كرر هذه العملية عدة مرات - وستجد أن هناك نسبة عدد النقاط داخل نصف الدائرة مقابل العدد الإجمالي الذي تم طرحه ، اتصل بهذه النسبة x.

نظرًا لأن مساحة المربع هي r times r ، فيمكنك استنتاج أن مساحة نصف الدائرة x أضعاف r أضعاف r (أي ، أضعاف r مربعة). وبالتالي س مرات 4 سوف تعطيك بي.

هذه ليست طريقة سريعة للاستخدام. لكنه مثال رائع على طريقة مونت كارلو. وإذا نظرت حولك ، فقد تجد أنه يمكن حل العديد من المشكلات بخلاف مهاراتك الحاسوبية بهذه الطرق.


استخدم صيغة تشبه Machin

176 * arctan (1/57) + 28 * arctan (1/239) - 48 * arctan (1/682) + 96 * arctan(1/12943) 

[; \left( 176 \arctan \frac{1}{57} + 28 \arctan \frac{1}{239} - 48 \arctan \frac{1}{682} + 96 \arctan \frac{1}{12943}\right) ;], for you TeX the World people.

نفذت في المخطط ، على سبيل المثال:

(+ (- (+ (* 176 (atan (/ 1 57))) (* 28 (atan (/ 1 239)))) (* 48 (atan (/ 1 682)))) (* 96 (atan (/ 1 12943))))


بدلاً من تعريف pi على أنه ثابت ، أستخدم acos(-1) دائمًا.


بي هو بالضبط 3! [البروفيسور فرينك (سمبسنز)]

نكتة ، ولكن هنا واحدة في C # (.NET Framework مطلوب).

using System;
using System.Text;

class Program {
    static void Main(string[] args) {
        int Digits = 100;

        BigNumber x = new BigNumber(Digits);
        BigNumber y = new BigNumber(Digits);
        x.ArcTan(16, 5);
        y.ArcTan(4, 239);
        x.Subtract(y);
        string pi = x.ToString();
        Console.WriteLine(pi);
    }
}

public class BigNumber {
    private UInt32[] number;
    private int size;
    private int maxDigits;

    public BigNumber(int maxDigits) {
        this.maxDigits = maxDigits;
        this.size = (int)Math.Ceiling((float)maxDigits * 0.104) + 2;
        number = new UInt32[size];
    }
    public BigNumber(int maxDigits, UInt32 intPart)
        : this(maxDigits) {
        number[0] = intPart;
        for (int i = 1; i < size; i++) {
            number[i] = 0;
        }
    }
    private void VerifySameSize(BigNumber value) {
        if (Object.ReferenceEquals(this, value))
            throw new Exception("BigNumbers cannot operate on themselves");
        if (value.size != this.size)
            throw new Exception("BigNumbers must have the same size");
    }

    public void Add(BigNumber value) {
        VerifySameSize(value);

        int index = size - 1;
        while (index >= 0 && value.number[index] == 0)
            index--;

        UInt32 carry = 0;
        while (index >= 0) {
            UInt64 result = (UInt64)number[index] +
                            value.number[index] + carry;
            number[index] = (UInt32)result;
            if (result >= 0x100000000U)
                carry = 1;
            else
                carry = 0;
            index--;
        }
    }
    public void Subtract(BigNumber value) {
        VerifySameSize(value);

        int index = size - 1;
        while (index >= 0 && value.number[index] == 0)
            index--;

        UInt32 borrow = 0;
        while (index >= 0) {
            UInt64 result = 0x100000000U + (UInt64)number[index] -
                            value.number[index] - borrow;
            number[index] = (UInt32)result;
            if (result >= 0x100000000U)
                borrow = 0;
            else
                borrow = 1;
            index--;
        }
    }
    public void Multiply(UInt32 value) {
        int index = size - 1;
        while (index >= 0 && number[index] == 0)
            index--;

        UInt32 carry = 0;
        while (index >= 0) {
            UInt64 result = (UInt64)number[index] * value + carry;
            number[index] = (UInt32)result;
            carry = (UInt32)(result >> 32);
            index--;
        }
    }
    public void Divide(UInt32 value) {
        int index = 0;
        while (index < size && number[index] == 0)
            index++;

        UInt32 carry = 0;
        while (index < size) {
            UInt64 result = number[index] + ((UInt64)carry << 32);
            number[index] = (UInt32)(result / (UInt64)value);
            carry = (UInt32)(result % (UInt64)value);
            index++;
        }
    }
    public void Assign(BigNumber value) {
        VerifySameSize(value);
        for (int i = 0; i < size; i++) {
            number[i] = value.number[i];
        }
    }

    public override string ToString() {
        BigNumber temp = new BigNumber(maxDigits);
        temp.Assign(this);

        StringBuilder sb = new StringBuilder();
        sb.Append(temp.number[0]);
        sb.Append(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator);

        int digitCount = 0;
        while (digitCount < maxDigits) {
            temp.number[0] = 0;
            temp.Multiply(100000);
            sb.AppendFormat("{0:D5}", temp.number[0]);
            digitCount += 5;
        }

        return sb.ToString();
    }
    public bool IsZero() {
        foreach (UInt32 item in number) {
            if (item != 0)
                return false;
        }
        return true;
    }

    public void ArcTan(UInt32 multiplicand, UInt32 reciprocal) {
        BigNumber X = new BigNumber(maxDigits, multiplicand);
        X.Divide(reciprocal);
        reciprocal *= reciprocal;

        this.Assign(X);

        BigNumber term = new BigNumber(maxDigits);
        UInt32 divisor = 1;
        bool subtractTerm = true;
        while (true) {
            X.Divide(reciprocal);
            term.Assign(X);
            divisor += 2;
            term.Divide(divisor);
            if (term.IsZero())
                break;

            if (subtractTerm)
                this.Subtract(term);
            else
                this.Add(term);
            subtractTerm = !subtractTerm;
        }
    }
}

تطبق طريقة مونت كارلو ، كما ذُكر ، بعض المفاهيم العظيمة ، لكنها ، بالطبع ، ليست الأسرع ، وليس بالرصاص الطويل ، وليس بأي مقياس معقول. أيضًا ، كل هذا يتوقف على نوع الدقة التي تبحث عنها. أسرع ما أعرفه هو الرقم الذي يحتوي على أرقام مشفرة بشكل ثابت. بالنظر إلى Pi و Pi[PDF] ، هناك الكثير من الصيغ.

إليك طريقة تلتقي بسرعة - حوالي 14 رقمًا لكل تكرار. PiFast ، أسرع تطبيق الحالي ، هذه الصيغة مع FFT. سأكتب المعادلة ، لأن الكود واضح ومباشر. تم العثور على هذه الصيغة تقريبًا بواسطة Ramanujan واكتشفها Chudnovsky . هو في الواقع كيف قام بحساب عدة مليارات من الأرقام - لذلك ليست طريقة للتجاهل. سوف تغمر الصيغة بسرعة ، وبما أننا نقسم الفصائل ، فسيكون من المفيد تأخير هذه الحسابات لإزالة المصطلحات.

أين،

أدناه هي خوارزمية برنت سالامين . تذكر ويكيبيديا أنه عندما يكون a و b "قريبين بما فيه الكفاية" فإن (a + b) ² / 4t سيكون تقريبًا π. لست متأكدًا مما يعنيه "الإغلاق الكافي" ، لكن من خلال اختباراتي ، حصل التكرار الواحد على رقمين ، واثنان حصلت عليهما 7 ، وثلاثة يحتويان على 15 ، بالطبع هذا مع الزوجي ، لذلك قد يكون هناك خطأ بناءً على تمثيله و يمكن أن يكون الحساب الحقيقي أكثر دقة.

let pi_2 iters =
    let rec loop_ a b t p i =
        if i = 0 then a,b,t,p
        else
            let a_n = (a +. b) /. 2.0 
            and b_n = sqrt (a*.b)
            and p_n = 2.0 *. p in
            let t_n = t -. (p *. (a -. a_n) *. (a -. a_n)) in
            loop_ a_n b_n t_n p_n (i - 1)
    in 
    let a,b,t,p = loop_ (1.0) (1.0 /. (sqrt 2.0)) (1.0/.4.0) (1.0) iters in
    (a +. b) *. (a +. b) /. (4.0 *. t)

أخيرًا ، ماذا عن بعض لعبة غولف pi (800 رقم)؟ 160 حرفا!

int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}

حساب π من منطقة الدائرة :-)

<input id="range" type="range" min="10" max="960" value="10" step="50" oninput="calcPi()">
<br>
<div id="cont"></div>

<script>
function generateCircle(width) {
    var c = width/2;
    var delta = 1.0;
    var str = "";
    var xCount = 0;
    for (var x=0; x <= width; x++) {
        for (var y = 0; y <= width; y++) {
            var d = Math.sqrt((x-c)*(x-c) + (y-c)*(y-c));
            if (d > (width-1)/2) {
                str += '.';
            }
            else {
                xCount++;
                str += 'o';
            }
            str += "&nbsp;" 
        }
        str += "\n";
    }
    var pi = (xCount * 4) / (width * width);
    return [str, pi];
}

function calcPi() {
    var e = document.getElementById("cont");
    var width = document.getElementById("range").value;
    e.innerHTML = "<h4>Generating circle...</h4>";
    setTimeout(function() {
        var circ = generateCircle(width);
        e.innerHTML  = "<pre>" + "π = " + circ[1].toFixed(2) + "\n" + circ[0] +"</pre>";
    }, 200);
}
calcPi();
</script>


فقط صادفت هذا واحد يجب أن يكون هنا للتأكد من اكتماله:

حساب PI في بيت

لديها خاصية لطيفة إلى حد ما أنه يمكن تحسين الدقة مما يجعل البرنامج أكبر.

Here بعض الأفكار عن اللغة نفسها


في الأيام الخوالي ، مع أحجام الكلمات الصغيرة وعمليات الفاصلة العائمة البطيئة أو غير الموجودة ، اعتدنا على القيام بأشياء مثل هذه:

/* Return approximation of n * PI; n is integer */
#define pi_times(n) (((n) * 22) / 7)

بالنسبة للتطبيقات التي لا تتطلب الكثير من الدقة (ألعاب الفيديو ، على سبيل المثال) ، هذا سريع للغاية ودقيق بدرجة كافية.


مع الزوجي:

4.0 * (4.0 * Math.Atan(0.2) - Math.Atan(1.0 / 239.0))

سيكون هذا دقيقًا حتى 14 منزلة عشرية ، وهو ما يكفي لملء ضعف (ربما يكون عدم الدقة لأن بقية الكسور العشرية في ظلال القوس مقطوعة).

أيضا Seth ، انها 3.14159265358979323846 3 ، وليس 64.


هذا الإصدار (في دلفي) ليس شيئًا خاصًا ، لكنه أسرع على الأقل من الإصدار الذي نشره نيك هودج على مدونته :). على الجهاز الخاص بي ، يستغرق الأمر حوالي 16 ثانية للقيام بمليارات التكرار ، مما يعطي قيمة 3.14159265 25879 (الجزء الدقيق غامق).

program calcpi;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  start, finish: TDateTime;

function CalculatePi(iterations: integer): double;
var
  numerator, denominator, i: integer;
  sum: double;
begin
  {
  PI may be approximated with this formula:
  4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 .......)
  //}
  numerator := 1;
  denominator := 1;
  sum := 0;
  for i := 1 to iterations do begin
    sum := sum + (numerator/denominator);
    denominator := denominator + 2;
    numerator := -numerator;
  end;
  Result := 4 * sum;
end;

begin
  try
    start := Now;
    WriteLn(FloatToStr(CalculatePi(StrToInt(ParamStr(1)))));
    finish := Now;
    WriteLn('Seconds:' + FormatDateTime('hh:mm:ss.zz',finish-start));
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

يعجبني هذا البرنامج حقًا ، لأنه يقارب π من خلال النظر إلى منطقته.

IOCCC 1988: westley.c

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

يوجد في الواقع كتاب كامل مخصص (من بين أشياء أخرى) لأساليب سريعة لحساب \ pi: "Pi و AGM" ، بقلم جوناثان وبيتر بوروين ( متاح في أمازون ).

لقد درست اجتماع الجمعية العامة العادية والخوارزميات ذات الصلة إلى حد ما: إنه أمر مثير للاهتمام للغاية (على الرغم من أنه غير تافه في بعض الأحيان).

لاحظ أنه لتنفيذ معظم الخوارزميات الحديثة لحساب \ pi ، ستحتاج إلى مكتبة حسابية متعددة الدرجات (يعد GMP اختيارًا جيدًا ، على الرغم من مرور الوقت منذ آخر مرة استخدمت فيها).

يوجد التعقيد الزمني لأفضل الخوارزميات في O (M (n) log (n)) ، حيث M (n) هي التعقيد الزمني لضرب عدد صحيحين n-bit (M (n) = O (n) log (n) log (log (n))) باستخدام خوارزميات تستند إلى FFT ، والتي تكون مطلوبة عادةً عند حساب أرقام \ pi ، ويتم تنفيذ هذه الخوارزمية في GMP).

لاحظ أنه على الرغم من أن الرياضيات وراء الخوارزميات قد لا تكون تافهة ، إلا أن الخوارزميات نفسها عادة ما تكون عبارة عن بضعة أسطر من الشفرة الزائفة ، وعادة ما يكون تنفيذها واضحًا جدًا (إذا اخترت عدم كتابة حساب التعدد الخاص بك :-)).





pi