हम सभी जानते हैं कि
exp(x)=∑n=0∞xnn!=1+x+12x2+…
इसका तात्पर्य है|x|≪1, हमारे पासexp(x)≈1+x। इसका मतलब यह है कि अगर हमें फ्लोटिंग पॉइंटexp(x)−1में मूल्यांकन करना है, तो|x|≪1विपत्तिपूर्ण रद्दीकरण हो सकता है।
यह अजगर में आसानी से दिखाया जा सकता है:
>>> from math import (exp, expm1)
>>> x = 1e-8
>>> exp(x) - 1
9.99999993922529e-09
>>> expm1(x)
1.0000000050000001e-08
>>> x = 1e-22
>>> exp(x) - 1
0.0
>>> expm1(x)
1e-22
सटीक मान
exp(10−8)−1exp(10−22)−1=0.000000010000000050000000166666667083333334166666668…=0.000000000000000000000100000000000000000000005000000…
सामान्य रूप से "सटीक" का कार्यान्वयन exp
और expm1
1ULP से अधिक नहीं होना चाहिए (अर्थात अंतिम स्थान की एक इकाई)। हालांकि, इस सटीकता को प्राप्त करने के बाद से "धीमा" कोड होता है, कभी-कभी एक तेज, कम सटीक कार्यान्वयन उपलब्ध होता है। उदाहरण के लिए CUDA में हमारे पास है , expf
और expm1f
जहां f
उपवास के लिए खड़ा है। CUDA C प्रोग्रामिंग गाइड के अनुसार , ऐप। डीexpf
2ULP की कोई त्रुटि है।
यदि आप कुछ यूएलपीएस के क्रम में त्रुटियों के बारे में परवाह नहीं करते हैं, तो आमतौर पर घातीय फ़ंक्शन के विभिन्न कार्यान्वयन समान होते हैं, लेकिन सावधान रहें कि कीड़े कहीं छिपे हो सकते हैं ... ( पेंटियम एफडिव बग याद रखें ?)
तो यह बहुत है कि स्पष्ट है expm1
गणना करने के लिए इस्तेमाल किया जाना चाहिए exp(x)−1 छोटा सा के लिए x । सामान्य x लिए इसका उपयोग करना हानिकारक नहीं है, क्योंकि expm1
इसकी पूरी सीमा पर सटीक होने की उम्मीद है:
>>> exp(200)-1 == exp(200) == expm1(200)
True
(उपरोक्त उदाहरण में 1exp(200) 1ULP से नीचे है , इसलिए सभी तीन अभिव्यक्ति बिल्कुल एक ही फ्लोटिंग पॉइंट नंबर पर लौटती हैं ।)
ऐसा ही एक चर्चा उलटा कार्यों के लिए रखती है log
और log1p
के बाद से log(1+x)≈x के लिए |x|≪1 ।
log1p
आप उल्लेख कर रहे हैं (विशेषकर यह कैसे लागू किया जाता है, इसलिए हमें अनुमान लगाने की आवश्यकता नहीं है)।