Prettify صيغة الرياضيات في التعليمات البرمجية

لدي وظيفة لحساب التوزيع الطبيعي في بايثون:

def norm_cdf(z):
  """ Use the norm distribution functions as of Gale-Church (1993) srcfile. """
  # Equation 26.2.17 from Abramowitz and Stegun (1964:p.932)

  t = 1.0/(1+0.2316419*z) # t = 1/(1+pz) , p=0.2316419
  probdist = 1 - 0.3989423*math.exp(-z*z/2) * ((0.319381530 * t)+ \
                                         (-0.356563782* math.pow(t,2))+ \
                                         (1.781477937 * math.pow(t,3)) + \
                                         (-1.821255978* math.pow(t,4)) + \
                                         (1.330274429 * math.pow(t,5)))
  return probdist

ولكن يجب أن ألتزم بـ PEP8 و 80 char chargin ، ومن هنا فإن s قبيح. ما الطريقة الأخرى التي يمكنني بها تشفير الرمز الخاص بي؟

في شكل رياضي ،

$$\begin{align*} \textrm{norm_cdf}(z) = 1 - 0.3989423 e^\frac{-z^2}{2} (&1.330274429 t^5 - 1.821255978 t^4 \\ &+ 1.781477937 t^3 - 0.356563782 t^2 + 0.319381530 t ) \end{align*}$$

أين

$$ t = \ frac {1} {1 + 0.2316419 z} $$

42
تعليقات Jeez في Python قبيحة ... من ناحية أخرى ، هل يمكنك القيام بشيء مثل C-style typedef للثوابت الرياضية الخاصة بك؟ من شأنه أن يجعل من الكود الجحيم من أكثر قابلية للقراءة ، ايمو. شيء مثل typdef 0.319381530 NORMALITY . لكنك تعلم ، واختيار أفضل الأسماء والاشياء. بالنسبة إلى بايثون ، يمكنك الحصول على جميع ثوابتك في أعلى الطريقة (للقراءة) ، مثل NORMALITY = 0.319381530 . هذا هو طريقتنا المفضلة لتنظيم الوظائف الرياضية على أي حال.
وأضاف المؤلف tai, مصدر
Davidmh آه ، حسنًا. كان هذا سوء الفهم :)
وأضاف المؤلف tai, مصدر
Davidmh أعلم أنه لا يوجد typedef في Python ، ولهذا السبب اقترحت فقط تعريف "ثابت" مثل NORMALITY = 0.319381530 . أنا شخصياً لا أحب نهج القائمة كما هو مقترح في الإجابة في Davidmh: coeff = [1 ، 0.319381530 ، -0.356563782 ، 1.781477937 ، -1.821255978 ، 1.330274429] إذا كان هناك الكثير من الثوابت ، باستخدام coeff [0] ، coeff [ 1] وما إلى ذلك يبدأ يصبح غير قابل للقراءة في دالة طويلة ، خاصةً الدالات التي تستخدم الثوابت عدة مرات. مرة أخرى ، فقط رأيي.
وأضاف المؤلف tai, مصدر
ChrisCirefice Er ، لا يعمل هذا typedef s في C.
وأضاف المؤلف Nic Hartley, مصدر
@ 200_success يحب لصيغة الصيغة !!
وأضاف المؤلف hippytea, مصدر
ChrisCirefice قائمة مفيدة في حلقة ، والمعاملات لا تحمل أي معنى معين من خلال أنفسهم ، وأنها لن يعاد استخدامها إلا في expresions مشتقة من كثيرات الحدود (المشتقات ، التكاملات ، الخ).
وأضاف المؤلف Davidmh, مصدر
ChrisCirefice لا يوجد شيء مثل typedefs في بايثون. حفظ معاملات في قائمة هو نهج أكثر قابلية للقراءة.
وأضاف المؤلف Davidmh, مصدر

8 إجابة

دعني اقتبس الكتاب الرائع الوصفات العددية في C ++ (ولكن ينطبق أيضا):

نفترض أنك تعرف ما يكفي مطلقًا لتقييم كثير الحدود بهذه الطريقة:

<�قبل> <�رمز> ص = ج [0] + ج [1] * س + ج [2] * س * س + ج [3] * س * س * س + ج [4] * س * س * س * س. </القانون> </قبل>      

أو (أسوأ من ذلك!) ،

<�قبل> <�رمز> ص = ج [0] + ج [1] * س + ج [2] * الأسرى (س، 2.0) + ج [3] * الأسرى (س، 3.0) + ج [4] * الأسرى (خ، 4.0)؛ </القانون> </قبل>      

عندما تأتي ثورة (الكمبيوتر) ، سيتم تنفيذ جميع الأشخاص الذين يتم إدانتهم بمثل هذا السلوك الإجرامي ، ولن يتم تنفيذ برامجهم!

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

هناك سببان لعدم القيام بذلك: الدقة والأداء. الطريقة الصحيحة لتقييم كثير الحدود هي كالتالي:

-t * (0.319381530  +  t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + 1.330274429 * t))))

And you can, of course, split at your convenience, as the newlines inside parenthesis are ignored. Remember the PEP: " The preferred place to break around a binary operator is after the operator, not before it."

-t * (0.319381530  +  t * (-0.356563782 +
    t * (1.781477937 + t * (-1.821255978 + 1.330274429 * t))))

بديل آخر هو حفظ معاملات في قائمة:

coeff = [0, 0.319381530, -0.356563782, 1.781477937, -1.821255978, 1.330274429]
poly = coeff[-1]
for c in coeff[-2::-1]:
    poly *= x
    poly += c

أقوم بعمليات في مكان لتجنب تخصيص الذاكرة وإلغاء تخصيصها ، ولكن هذا لا ينطبق إلا إذا كانت x عبارة عن مصفوفة NumPy. إذا كنت تقوم بالتقييم على رقم واحد ، فيمكنك استخدام التعبير الأصغر بدلاً من ذلك:

poly = poly * x + coeff[i]

لكنني سألتزم بالأولى لأنها أكثر عمومية.

بالطبع ، يجب ضرب النتيجة من قبل prefactor:

return 1 - 0.3989423*math.exp(-z*z/2) * poly

أو ، إذا كنت تريد أن تفعل ذلك في مكان:

z2 = z * z # Be careful not to modify your input!
z2 *= 0.5  # Multiplication is faster than division.
np.exp(z2, out=z2)

probd = z2 * poly
probd *= -0.3989423
probd += 1
return probd

مسار المكافأة:

إذا كنت تقوم بتطبيق هذه الوظيفة على صفائف كبيرة (أكثر من ألف رقم) ، فقد تستفيد من استخدام التقنية الأولى في numexpr:

expr += '1 - 0.3989423* exp(-z * z/2) * '
expr += '(-t * (0.319381530  +  t * (-0.356563782 +  t * '
expr += '(1.781477937 + t * (-1.821255978 + 1.330274429 * t)))))'
ne.evaluate(expr)

هذا سوف يقوم بتجميع التعبير نيابة عنك ويستخدم بشفافية العديد من النوى لديك.

40
وأضاف
EmilioMBumachar يعتمد على كثيرات الحدود. ولكن بالنسبة إلى العديد من كثيرات الحدود المستخدمة في الممارسة ، فإن النهج الساذج سينتج عنه طرح قيم كبيرة متشابهة الحجم مما يزيد من الخطأ المطلق لأن الأعداد الأكبر لها أخطاء تمثيل مطلقة أكبر باستخدام نقاط floatingpoints.
وأضاف المؤلف Ben Crowell, مصدر
أستطيع أن أرى عقوبة الأداء الشديدة لتنفيذها بأي من الطرق المحبطة ، ولكن ليس عقوبة الدقة. لماذا هو سيء للدقة؟ لقد طرحتها على SO: stackoverflow.com/q/25203873/174365
وأضاف المؤلف Czyrek, مصدر
تُعرف طريقة تقييم كثيرات الحدود هذه بـ "مخطط هورنر" (أو طريقة تعتمد على المكان الذي تعيش فيه).
وأضاف المؤلف mikeazo, مصدر
ربما أفتقد بعض السياق ، ولكن يبدو أنك تقوم بإعداد رمز أطول وأقوى من أجل السرعة ، والتي لا تبدو مصدر قلق لـ OP على الإطلاق.
وأضاف المؤلف jas663, مصدر
لا أعتقد أن هناك أي استخدام في استخدام "العديد من النوى لديك" لهذا التعبير. من السهل جدا أن تكون متوازية بكفاءة.
وأضاف المؤلف Yahya Uddin, مصدر
Ruslan "للصفائف الكبيرة". تطبيق نفس الوظيفة لأرقام 1e4 لا تستفيد من التنفيذ المتوازي.
وأضاف المؤلف Davidmh, مصدر
FranciscoCouzo هو تحسين ممتاز! لقد قمت بتحريره
وأضاف المؤلف Davidmh, مصدر
@ raptortech97 أنا أعطي كلا الخيارين. على أي حال ، فإن الجزء المهم هو أن تقييم كثير الحدود يجب أن يتم بشكل صحيح ليكون دقيقا.
وأضاف المؤلف Davidmh, مصدر
بدلاً من استخدام xrange (len (coeff) - 2، -1، -1) ، ثم فهرسة coeff بواسطة i ، فما استقاموا لكم فاستقيموا تتكرر خلال coeff [-2 :: - 1]
وأضاف المؤلف Francisco Couzo, مصدر

As it turns out, a similar question was asked recently on Math.SE. Rather than , take advantage of built-in functionality in Python.

يعد norm_cdf (z) مجرد تقدير رقمي لـ

$$ P (z) = \ frac {1} {\ sqrt {2 \ pi}} \ int _ {- \ infty} ^ {z} e ^ {- t ^ 2/2} \ dt = \ int _ {- \ infty} ^ {z} Z (t) \ dt = \ frac {1} {2} \ left (1 + \ mathrm {erf} \ left (\ frac {z} {\ sqrt {2}} \ right) \ right) = \ frac {1} {2} \ mathrm {erfc} \ left (- \، \ frac {z} {\ sqrt {2}} \ right) $$

لذلك ، يمكنك فقط استخدام math.erfc() (متوفر منذ Python 2.7) والحصول على نتيجة أكثر دقة (خاصة بالنسبة للقيم السلبية جدًا من \ $ z \ $).

import math

def norm_cdf(z):
    return 0.5 * math.erfc(-x/math.sqrt(2))

والأفضل من ذلك ، فقط استخدم scipy.stats.norm. قوات الدفاع المدني() </القانون> !

22
وأضاف
GraniteRobert على العكس من ذلك ، فإن norm_cdf (z) في السؤال هو التقريب القلوي. norm_cdf (0) هو 0.499999975962 بدلاً من 0.5. أي z ≤ -2.0 ينتج نتائج سلبية. لا يحتوي 0.5 * math.erfc (-x/math.sqrt (2)) على أي من هذه المشاكل.
وأضاف المؤلف wjv, مصدر
أو ، يمكنك سرقة التنفيذ العام لـ erf() .
وأضاف المؤلف wjv, مصدر
لماذا لا تتطلب فقط أو إعادة توزيع SciPy إذا كان يعمل على Python ≤ 2.6؟
وأضاف المؤلف wjv, مصدر
alvas جميع البيانات الخاصة بك هي فوق المتوسط؟
وأضاف المؤلف wjv, مصدر
في الواقع كان يفترض norm_cdf() أن يأخذ دائما بعض القيمة المطلقة لوظيفة تكلفة أخرى ، لذلك لا بأس.
وأضاف المؤلف hippytea, مصدر
لأن المدخلات لا يمكن أبدًا أن تكون سالبة لأن الحد الأدنى لأي طول من الجمل هو 0 .
وأضاف المؤلف hippytea, مصدر
لدي الكود الكامل مع محاولة باستثناء عند استيراد scipy.stats.norm.cdf() ، فقط في حالة ، لم يتم تثبيت المستخدمين scipy ولكن math.erfc </رمز> سيكون جيدا.
وأضاف المؤلف hippytea, مصدر
ولكن أعتقد أنه سوف تخلص من <= الحمر 2.6 المستخدمين ...
وأضاف المؤلف hippytea, مصدر
يجب توخي الحذر قبل التغيير إلى خوارزمية مختلفة لإجراء الحساب "نفسه". من 8 تقريب أو مختلفة تقريبًا في Abramowitz و Stegun (A & S) لوظيفة التوزيع العادية ، اختار أحدهم هذا التقريب الخاص. ربما كان هناك سبب جيد جدا للخيار. لا تفترض أن وظيفة المكتبة الجاهزة ستعطي الدقة الكافية للمشكلة المطروحة ، ما لم تأخذ الوقت الكافي لفهم التفاصيل القبيحة للحساب. الناس الذين يفتشون في A & S لا يميلون إلى أن يكونوا مستخدمين عاديين. دقة و حدود الخطأ قد تكون مهمة جدا.
وأضاف المؤلف atos, مصدر
@ 200_success: يقول A & S 26.2.17 صراحةً أن المدخلات الصالحة غير سالبة. لا يجب استدعاء الرمز بالقيم السالبة ، وفي بيئة قد تكون فيها المكالمات غير الصالحة محتملة ، ربما يجب أن تتضمن الشيك. يتم سرد حد الخطأ كـ 7.5 * 10 ** -8 . هل تم تحديد الدقة بطريقة ما لـ math.erfc ؟ أنا لا أقترح إما خوارزمية أفضل أو أسوأ ، أنا فقط أقول يجب أن يفهم المقايضات في سياق المشكلة التي يتم حلها.
وأضاف المؤلف atos, مصدر

سأتناول فقط ما يسمى "الأعداد السحرية" التي ذكرها العديد من المراجعين.

في بعض الأحيان ، عندما تعمل في الرياضيات البحتة ، ما يبدو للوهلة الأولى أنه "رقم سحري" فعلاً غير . قد يكون أن الأرقام نفسها ليست سوى جزء من بيان المشكلة. أعتقد أن السؤال يتلخص في هذا: هل يمكنك أن تكتب اسمًا أكثر وصفًا من الرقم؟ إذا كان هناك اسم جيد ، فمن المحتمل أن تستخدمه.

للوهلة الأولى ، اعتقدت أن أرقامك كانت جزءًا متأصلاً من المشكلة. ولكن عندما نظرت إلى Abramowitz و Stegun ، رأيت أن الصيغة المشار إليها قد سميت بالفعل ثوابتك البشعة. الأسماء

p (التي ذكرتها في تعليق) ، و b1 من خلال b5 . يجب عليك استخدام هذه الأسماء في التعليمة البرمجية ، لأنها تنشئ رابطًا واضحًا جدًا لتعريف الصيغة الأصلي.

عندما قررت أنه من الأفضل إضافة التعليق p = 0.2316419 ، فقد كان ذلك دليلاً قوياً على أن الاسم يجب . (وبمجرد أن تشير code p = 0.2316419 ، يجب إزالة التعليق .)

بالمناسبة ، كان من الجيد جدًا تضمين مرجع Abramowitz و Stegun الدقيق في التعليق.

18
وأضاف

بدلاً من math.pow ، استخدم المشغل builtin ** . لا تحتاج إلى \ s في EOL ، لأن الأقواس المحيطة بالتعبير تسمح لها بتوسيع سطور متعددة ضمنيًا. لذا بعد إجراء كلتا هذين التغييرين ، سأنتهي مع:

def norm_cdf(z):
    """ Use the norm distribution functions as of Gale-Church (1993) srcfile. """
    # Equation 26.2.17 from Abramowitz and Stegun (1964:p.932)

    t = 1.0/(1 + 0.2316419*z) # t = 1/(1+pz) , p=0.2316419
    probdist = 1.0 - (   (0.319381530  * t)
                       + (-0.356563782 * t**2)
                       + (1.781477937  * t**3)
                       + (-1.821255978 * t**4)
                       + (1.330274429  * t**5)) * 0.3989423*math.exp(-z*z/2)
    return probdist

أنا أيضا إعادة ترتيب واحدة من مضاعفات لجعل الأسبقية أكثر وضوحا وقابلة للقراءة.

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

16
وأضاف

لست متأكدا مما إذا كان هذا يساعد ولكن يمكنك بسهولة تحديد وظيفة لتقييم قيمة polynom في موضع معين

def evaluate_polynom(pol, x):
    return sum(a * math.pow(x, i) for i, a in enumerate(pol))

ثم

(0.319381530 * t) + (-0.356563782* math.pow(t,2)) + (1.781477937 * math.pow(t,3)) + (-1.821255978* math.pow(t,4)) + (1.330274429 * math.pow(t,5))

يصبح:

evaluate_polynom([0, 0.319381530, -0.356563782, 1.781477937, -1.821255978, 1.330274429], t)
15
وأضاف
من الواضح أنني لا أملك معرفة كافية لوضع هذا في وظيفة ذات اسم ذي معنى ، ولكن لست متأكدًا من أن هذا مطلوب. أعتقد أنه يجلب مستوى التجريد المطلوب لجعله يبدو مثل الأشياء الرياضية المتضمنة ونقل هذا إلى مكان مختلف قد يكسر الصيغة الرياضية متباعدة.
وأضاف المؤلف Mike, مصدر
قد يكون nitpick الوحيد لدي هو إعادة تسمية pol إلى coeff أو معاملات لجعلها أكثر وضوحًا ، أو ربما استخدام البنية كما هو موضح أدناه؟
وأضاف المؤلف jmagnusson, مصدر
إذا كان هذا صحيحًا ، فيمكنك تحديد وظيفة أخرى تستدعي مقتطف الشفرة الذي وصفته ، كطريقة من نوع المساعد.
وأضاف المؤلف Pimgd, مصدر

على خطر (أبعد) إثارة غضب المشرفين ، سأنصح بعدم اتباع أي نصيحة حول الأرقام التي تنشأ من أي من الكتب وصفات 1 .

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

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

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


<�الفرعية> 1. للإشارة ، راجع النقد مثل: http : //www.stat.uchicago.edu/~lekheng/courses/302/wnnr/nr.html
http://www.lysator.liu.se/c/ ارقام-وصفات في وc.html
أعتقد أن ملخصًا أكثر دقة من "رائع" هو: "لقد اكتشفت أن وصفات عددية تقدم معلومات كافية لشخص ما ليقع في ورطة ، لأنه بعد قراءة NR ، يعتقد المرء أن الشخص يفهم ماذا يحدث هنا." </الفرعي>

6
وأضاف

بينما:

a*x**3 + b*x**2 + c*x = ((a*x + b)*x + c)*x

h/t @ Emily L. لمرجع "Horner":

https://en.wikipedia.org/wiki/Horner٪27s_method

و h/t @ Davidmh لملاحظة التحسينات في السرعة الحسابية/الدقة لهذه الطريقة

ذكرها غايل الكنيسة مثل هذا في عام 1990:

import math

def pnorm(z):

    t = 1/(1 + 0.2316419 * z)
    pd = (1 - 0.3989423 *
      math.exp(-z * z/2) *
        ((((1.330274429 * t - 1.821255978) * t
           + 1.781477937) * t - 0.356563782) * t + 0.319381530) * t)

    return pd

هذه الطريقة تتجنب بشكل ملائم مشكلة t ^ n.

الاقتباس:

enter image description here

enter image description here

مصدر:

http://www.aclweb.org/anthology/J93-1004

صفحة 21 من 28 في ملف pdf

صفحة 95 من اليومية اللغويات الحاسوبية المجلد 19 ، رقم 1

أنا قد "prettify" إلى:

def pnorm(z):

t = 1/(1 + 0.2316419 * z)
pd = (1 - 0.3989423 * math.exp(-z * z/2) *
      ((((1.330274429 * t - 
          1.821255978) * t + 
          1.781477937) * t - 
          0.356563782) * t + 
          0.319381530) * t )

return pd

إذا قمت بفحص

أبرومويتز وستيجون ، كتيب الوظائف الرياضية

الصفحة 932 معادلة 26.2.17

الاقتباس:

http://people.math.sfu.ca/~cbm/aands/ page_932.htm

ستجد هذا:

enter image description here

يمكننا من خلاله إنشاء جدول يعطينا:

def pnorm(z):

    p  =  0.2316419
    b1 =  0.319381530
    b2 = -0.356563782
    b3 =  1.781477937
    b4 = -1.821255978
    b5 =  1.330274429
    t = 1/(1 + p * z)
    pd = (1 - 0.3989423 * math.exp(-z * z/2) *
          ((((b5 * t + b4) * t + b3) * t + b2) * t + b1) * t )

    return pd

ثم من الصفحة السابقة ؛ 931 سوف تجد:

enter image description here

Zx = (1/√(2* π))*e(-z*z/2)

في الثعبان:

Zx = (1/math.sqrt(2* math.pi))*math.exp(-z*z/2)

ونجد أن (1/√ (2 * π)) = 0.3989423

أيضا ، أعتقد أنني أحب هذا:

t * (b1 + t * (b2 + t * (b3 + t * (b4 + t * b5))))

افضل من:

(((b5 * t + b4) * t + b3) * t + b2) * t + b1) * t 

لذلك ، في النهاية:

import math

def pnorm(z):

    p  =  0.2316419
    b1 =  0.319381530
    b2 = -0.356563782
    b3 =  1.781477937
    b4 = -1.821255978
    b5 =  1.330274429
    t  = 1/(1 + p * z)
    Zx = (1/math.sqrt(2 * math.pi)) * math.exp(-z * z/2)
    pd = Zx *  t * (b1 + t * (b2 - t * (b3 + t * (b4 - t * b5))))

    return (1 - pd) 

التحقق من عملي ضد op

import matplotlib.pyplot as plt
import numpy as np
import math




def norm_cdf(z):
  """ Use the norm distribution functions as of Gale-Church (1993) srcfile. """
  # Equation 26.2.17 from Abramowitz and Stegun (1964:p.932)

  t = 1.0/(1+0.2316419*z) # t = 1/(1+pz) , p=0.2316419
  probdist = 1 - 0.3989423*math.exp(-z*z/2) * ((0.319381530 * t)+ \
                                         (-0.356563782* math.pow(t,2))+ \
                                         (1.781477937 * math.pow(t,3)) + \
                                         (-1.821255978* math.pow(t,4)) + \
                                         (1.330274429 * math.pow(t,5)))

  return probdist

for z in np.arange (-3,3,0.01):
    zf = pnorm(z)
    plt.plot(z,zf, c='red', marker = '.', ms=1)

for z in np.arange (-3,3,0.01):
    zf = norm_cdf(z)+0.1 #offset 0.1
    plt.plot(z,zf, c='blue', marker = '.', ms=1)

plt.show()
plt.pause(0.1)

enter image description here

كنت أتوقع أن يكون أسلوب هورنر أسرع ، لذلك أجريت اختبارًا زمنيًا ، واستبدل:

#Zx = (1.0/math.sqrt(2.0 * math.pi)) * math.exp(-z * z/2.0)
Zx = 0.3989423* math.exp(-z * z/2.0)

لجعلها عادلة ورفع مستوى قرار np.arrange إلى 0.0001:

t0 = time.time()
for z in np.arange (-3,3,0.0001):
    zf = pnorm(z)
t1 = time.time()
for z in np.arange (-3,3,0.0001):
    zf = norm_cdf(z)
t2 = time.time()

print ('pnorm time    : %s' % (t1-t0))
print ('norm_cdf time : %s' % (t2-t1))

والنتائج ، وتدور بلدي رباعية النواة AMD 7950 FM2 + ث/16G من الصعب جدا (وإن كان ذلك مع العديد من التطبيقات الأخرى التي تعمل) ... تحدى توقعاتي:

>>>
pnorm time    : 81.4725670815
norm_cdf time : 80.7865998745

طريقة هورنر لم تكن أسرع

2
وأضاف
أود أن أوصي أيضا تحسين الصيغ هنا مع MathJax. إذا كنت لا تعرف كيفية القيام بذلك ، يمكنني العمل عليه لاحقًا.
وأضاف المؤلف Jamal, مصدر
مرحبا بكم في مراجعة قانون StackExchange! جزء بسيط من التاريخ ، شكرًا على المشاركة.
وأضاف المؤلف Stephen Rauch, مصدر
لم أكن قد عملت مع Mathgax من قبل ، سأكون مهتمة بمعرفة نتيجة جمال. شكرا على الترحيب ستيفن راوخ
وأضاف المؤلف litepresence, مصدر

سأكون صادقا هنا: أنا أمتص تماما في الثعبان.

ومع ذلك ، هل من الممكن الإعلان عن بعض هذه القيم الحرفية الرقمية باعتبارها ثوابت؟ هذا من شأنه تنظيف التعليمات البرمجية الخاصة بك وتوضيح التعليمات البرمجية نفسها أكثر قليلاً كذلك.

1
وأضاف