Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

لنحسب π باستخدام SQL

إنه يوم باي! لنحسب قيمة باي باستخدام SQL

عيد Pi سعيد! راودتنا فكرة أن يكون من الممتع حساب pi باستخدام استعلامات SQL في ClickHouse. إليك ما توصّلنا إليه حتى الآن…

  1. يستخدم هذا المثال table function ‏numbers_mt في ClickHouse لإرجاع مليار صف، ولا يستغرق تنفيذ العملية الحسابية سوى 40 مللي ثانية:
SELECT 4 * sum(if(number % 2, -1, 1) / ((number * 2) + 1)) AS pi
FROM numbers_mt(1000000000.)

┌────────────────pi─┐
│ 3.141592652589797 │
└───────────────────┘

1 row in set. Elapsed: 0.432 sec. Processed 1.00 billion rows, 8.00 GB (2.32 billion rows/s., 18.53 GB/s.)
  1. يعالج المثال التالي أيضًا 1B رقمًا، لكن بوتيرة أبطأ:
SELECT 3 + (4 * sum(if((number % 2) = 0, if((number % 4) = 0, -1 / ((number * (number + 1)) * (number + 2)), 1 / ((number * (number + 1)) * (number + 2))), 0))) AS pi
FROM numbers_mt(2, 10000000000)

┌─────────────────pi─┐
│ 3.1415926525808087 │
└────────────────────┘

1 row in set. Elapsed: 9.825 sec. Processed 10.00 billion rows, 80.00 GB (1.02 billion rows/s., 8.14 GB/s.)
  1. هذا بالطبع هو المفضل لدينا في ClickHouse (وهو الأدق أيضًا!):
SELECT pi()

┌──────────────pi()─┐
│ 3.141592653589793 │
└───────────────────┘

1 row in set. Elapsed: 0.008 sec.
  1. يبدو أن صاحب هذا كان يعرف حساب المثلثات جيدًا:
SELECT 2 * asin(1) AS pi

┌────────────────pi─┐
│ 3.141592653589793 │
└───────────────────┘

1 row in set. Elapsed: 0.005 sec.
  1. إليك واجهة برمجة تطبيقات عملية تتيح لك تحديد عدد الخانات التي تريدها:
SELECT *
FROM url('https://api.pi.delivery/v1/pi?start=0&numberOfDigits=100', 'JSONEachRow')

┌───────────────content─┐
│ 3.1415926535897933e99 │
└───────────────────────┘

1 row in set. Elapsed: 0.556 sec.
  1. هذه الطريقة ذكية - إذ تستخدم دوال المسافة في ClickHouse:
WITH random_points AS
    (
        SELECT (rand64(1) / pow(2, 64), rand64(2) / pow(2, 64)) AS point
        FROM numbers(1000000000)
    )
SELECT (4 * countIf(L2Norm(point) < 1)) / count() AS pi
FROM random_points

┌──────────pi─┐
│ 3.141627208 │
└─────────────┘

1 row in set. Elapsed: 4.742 sec. Processed 1.00 billion rows, 8.00 GB (210.88 million rows/s., 1.69 GB/s.)
  1. إذا كنتَ فيزيائيًا، فستكتفي بهذا:
SELECT 22 / 7

┌─────divide(22, 7)─┐
│ 3.142857142857143 │
└───────────────────┘
  1. طريقة غير مباشرة أخرى (هذه من Alexey Milovidov) دقيقة حتى 7 منازل عشرية، وهي سريعة:
WITH
    10 AS length,
    (number / 1000000000.) * length AS x
SELECT pow((2 * length) * avg(exp(-(x * x))), 2) AS pi
FROM numbers_mt(1000000000.)

┌─────────────────pi─┐
│ 3.1415926890388595 │
└────────────────────┘

1 row in set. Elapsed: 1.245 sec. Processed 1.00 billion rows, 8.00 GB (803.25 million rows/s., 6.43 GB/s.)
Navigation