Log1p और expm1 का उपयोग कब किया जाना चाहिए?


30

मेरे पास एक सरल प्रश्न है जो वास्तव में Google के लिए कठिन है (विहित के अलावा हर कंप्यूटर वैज्ञानिक को फ्लोटिंग-प्वाइंट अंकगणितीय पेपर के बारे में पता होना चाहिए )।

जब इस तरह के रूप में भी कार्य करना चाहिए log1pया expm1के बजाय इस्तेमाल किया जा logऔर exp? इनका उपयोग कब नहीं किया जाना चाहिए? उन कार्यों के विभिन्न कार्यान्वयन उनके उपयोग के संदर्भ में कैसे भिन्न होते हैं?


2
Scicomp.SE में आपका स्वागत है! यह एक बहुत ही उचित सवाल है, लेकिन जवाब देना आसान होगा यदि आपने थोड़ा सा समझाया है जिसका log1p आप उल्लेख कर रहे हैं (विशेषकर यह कैसे लागू किया जाता है, इसलिए हमें अनुमान लगाने की आवश्यकता नहीं है)।
क्रिश्चियन क्लैसन

4
वास्तविक मान वाले तर्कों के लिए, log1p और expm1 ( x ) का उपयोग तब किया जाना चाहिए जब x छोटा हो, उदाहरण के लिए, जब फ्लोटिंग पॉइंट सटीकता में 1 + x = 1 हो। देखें, जैसे, docs.scipy.org/doc/numpy/reference/generated/numpy.expm1.html और docs.scipy.org/doc/numpy/reference/generated-numpy.log1p.html(x)(x)x1+x=1
गोहोकीस 14

@ChristianClason धन्यवाद, मैं ज्यादातर C ++ std या R की बात कर रहा हूं, लेकिन जैसा कि आप पूछते हैं कि मुझे लगता है कि कार्यान्वयन में अंतर के बारे में सीखना भी बहुत दिलचस्प होगा।
टिम


1
@ user2186862 "जब छोटा है" सही है, लेकिन न केवल "जब 1 + x = 1 में चल बिन्दु सटीकता" (जिसके लिए होता है एक्स 10 - 16 सामान्य डबल परिशुद्धता गणित में)। ऐसे कई पृष्ठ आपको बताते हैं कि वे पहले से ही उपयोगी होते हैं के लिए जुड़ा हुआ x 10 - 10 , उदाहरण के लिए। x1+x=1x1016x1010
फेडरिको पोलोनी

जवाबों:


25

हम सभी जानते हैं कि

exp(x)=n=0xnn!=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(108)1=0.000000010000000050000000166666667083333334166666668exp(1022)1=0.000000000000000000000100000000000000000000005000000

सामान्य रूप से "सटीक" का कार्यान्वयन expऔर expm11ULP से अधिक नहीं होना चाहिए (अर्थात अंतिम स्थान की एक इकाई)। हालांकि, इस सटीकता को प्राप्त करने के बाद से "धीमा" कोड होता है, कभी-कभी एक तेज, कम सटीक कार्यान्वयन उपलब्ध होता है। उदाहरण के लिए 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


1
यह उत्तर पहले से ही ओपी प्रश्न की टिप्पणियों में निहित था। हालाँकि, मैंने स्पष्टता के लिए एक लंबा (हालांकि बुनियादी) खाता देना उपयोगी समझा, इस उम्मीद में कि यह कुछ पाठकों के लिए उपयोगी होगा।
स्टेफानो एम।

ठीक है, लेकिन फिर एक बस निष्कर्ष निकाल सकता है "इसलिए मैं हमेशा exp के बजाय expm1 का उपयोग कर सकता हूं" ...
टिम

1
@ आपका निष्कर्ष गलत है: आप हमेशा expm1(x)इसके बजाय उपयोग कर सकते हैं exp(x)-1। बेशक exp(x) == exp(x) - 1सामान्य रूप से पकड़ में नहीं आता है।
स्टेफानो एम।

x1

1
expm1(x)0x1exp(x) - 1x1x<ϵϵ

1

के बीच के अंतर पर विस्तार करने के लिए logऔर log1pअगर लॉगरिदम:

Logarithm

logx0ln(x)x0ln(x)ln(1e)=1ln(1e10)=10

x0ln(x+1)0ln(1+1e)0.31ln(1+1e10)0.000045log1p

1log01log1p

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.