मैं कुछ जावा मैथ फ़ंक्शन मूल सी स्रोत कोड के माध्यम से खुदाई कर रहा था। विशेष रूप से tanh()
, क्योंकि मैं यह देखने के लिए उत्सुक था कि उन्होंने इसे कैसे कार्यान्वित किया। हालांकि, what I found मुझे हैरान कर दिया:जावा/सी: ओपनजेडीके देशी तन्ह() कार्यान्वयन गलत है?
double tanh(double x) {
...
if (ix < 0x40360000) { /* |x|<22 */
if (ix<0x3c800000) /* |x|<2**-55 */
return x*(one+x); /* tanh(small) = small */
...
}
टिप्पणी, taylor series of tanh(x) around 0 इंगित करता है, के साथ शुरू होता है:
tanh(x) = x - x^3/3 + ...
फिर क्यों यह दिखता है जैसे वे के रूप में इसे लागू किया:
tanh(x) = x * (1 + x)
= x + x^2
जो स्पष्ट रूप से सही विस्तार नहीं है, और tanh(x) = x
का उपयोग करने से भी बदतर अनुमान है (जो होगा तेज), के रूप में इस साजिश ने संकेत दिया:
(बोल्ड लाइन एक शीर्ष पर संकेत दिया है। अन्य ग्रे एक log(abs(x(1+x) - tanh(x)))
है। सिग्मोइड निश्चित रूप से tanh(x)
है।)
तो, क्या यह कार्यान्वयन में एक बग है, या यह कुछ समस्या ठीक करने के लिए हैक है (जैसे संख्यात्मक मुद्दों, जिन्हें मैं वास्तव में नहीं सोच सकता)? ध्यान दें कि मुझे उम्मीद है कि दोनों दृष्टिकोणों का नतीजा बिल्कुल वैसा ही होगा जैसा कि वास्तव में 1 + x को जोड़ने के लिए पर्याप्त mantisse बिट्स नहीं हैं, x < 2^(- 55) के लिए।
यह इस प्रकार का बकवास है जो रॉकेट को विस्फोट का कारण बनता है। –
पूरी तरह से 'tanh()' _odd_ फ़ंक्शन होने की अपेक्षा करता है, इसलिए 'y = f (x) -> y = -f (-x)'। 'x + x^2' टूटता है। केवल एक ही विचार है कि 'f (-0.0)' पर एक + चिह्न को मजबूर करना है, लेकिन यह 'tanh (x) = x + 0.0; 'के साथ करना आसान है। आईएमओ, एक त्रुटि जो खुद को 'x | <2 ** - 55' ... या गोलाकार झंडे के साथ कुछ नहीं दिखा सकती है। – chux
लक्ष्य प्लेटफ़ॉर्म पर 'x * (एक + x)' x + 0.0' को प्रभावित करने का एक मुश्किल तरीका हो सकता है? – chux