2010-02-10 12 views
8

विंडोज 7 पीसी पर जावा का उपयोग करना (यकीन नहीं है कि यह मायने रखता है) और Math.cos() को उन मानों पर कॉल करना जो 0 (जैसे pi/2) को वापस करना चाहिए छोटे मान लौटाते हैं, लेकिन छोटे मान, जब तक कि मैं गलतफहमी नहीं कर रहा हूं, शून्य से 1 ulp से अधिक हैं।जावा Math.cos() विधि 0 वापस नहीं आती है 0 अपेक्षित

Math.cos(Math.PI/2) = 6.123233995736766E-17 
Math.ulp(Math.cos(Math.PI/2)) = 1.232595164407831E-32 

क्या यह वास्तव में 1 उल के भीतर है और मैं बस उलझन में हूं? और क्या यह मामूली गलतता को हल करने के लिए एक स्वीकार्य रैपर विधि होगी?

public static double cos(double a){ 
    double temp = Math.abs(a % Math.PI); 
    if(temp == Math.PI/2) 
     return 0; 
    return Math.cos(a); 
} 
+0

@ dimo414 : सबसे पहले "यह निश्चित नहीं है कि यह महत्वपूर्ण है" पर एक टिप्पणी। अधिकांश मठ ऑपरेशन का व्यवहार ठीक से परिभाषित नहीं किया जाता है ताकि ओएस और सीपीयू मायने रख सकें। यदि आप गणित ऑपरेशन चाहते हैं जिसका व्यवहार सख्ती से परिभाषित किया गया है (जो तर्कसंगत रूप से समस्या निवारण के लिए आसान है) तो आप स्ट्रिक्टैथ का उपयोग करना चाहते हैं, मठ नहीं (निश्चित रूप से सख्त मैथ ऑपरेशंस शायद धीमे हो जाएंगे क्योंकि वे सीपीयू में उपलब्ध हार्डवेयर त्वरित ऑपरेशन का उपयोग नहीं कर सकते हैं)। – SyntaxT3rr0r

+0

Math.cos() StrictMath.cos() के लिए सिर्फ एक रैपर है, जो स्वयं ही एक मूल कार्य है। – dimo414

उत्तर

10

भूल जाते हैं कि Math.PI/2 एक सन्निकटन है मत करो। पर ऐसा न हो रहा है बिल्कुल pi/2, इसलिए cos(Math.PI/2) का परिणाम बिल्कुल 0. Math.cos की गणना Math.PI/2 द्वारा वापस सही मूल्य की कोज्या की एक बहुत सटीक संस्करण लौटने जा सकता होने के लिए नहीं जा रहा है।

+0

बहुत सच है, लेकिन यह कहा गया है, यह मेरे लिए सहज महसूस करता है कि यदि Math.PI पीआई के सबसे नज़दीक है, तो Math.PI/2 को पीआई/2 के सबसे नज़दीक होना चाहिए। और जब सेस() पीआई/2 और 3 पीआई/2 की परिभाषा शून्य से होती है, ऐसा लगता है कि उन संख्याओं का निकटतम दोहरा अनुमान Math.cos() को पास किया जाता है, यह शून्य भी होना चाहिए। हो सकता है कि यह सिर्फ खराब हो, (जो मेरे प्रश्न का क्रूक्स है) लेकिन यह मुझे सहज ज्ञान देता है। – dimo414

7

आपको कभी भी == का उपयोग युगल के साथ नहीं करना चाहिए। आपको हमेशा त्रुटि मार्जिन के भीतर करना होगा। 10 -17 यदि आप मुझसे पूछें तो अच्छी परिशुद्धता है। 10 -32 का अल्ट आकृति 10 -17 परिमाण के क्रम में डबल की सटीक है, 2.220446049250313E-16 10 परिमाण में संख्या की सटीकता है।

+0

@Slartibartfsat: +1, बिल्कुल। आपने मुझे इसमें हरा दिया। – SyntaxT3rr0r

+0

त्रुटि मार्जिन कम से कम दो बार ulp (पीआई/2) होना चाहिए, क्योंकि यह पीआई/2 की कमी है। सीओएस उस बिंदु पर -1 का व्युत्पन्न है, इसलिए परिणामस्वरूप पीआई/2 की अपर्याप्तता परिलक्षित होता है, साथ ही साथ कॉस की अपर्याप्तता भी दिखाई देती है। – starblue

+0

आम तौर पर मैं आपसे सहमत हूं, लेकिन मैं अपने अपवाद को जितना संभव हो सके उतने मामलों तक सीमित करना चाहता हूं, इसलिए यदि इनपुट Math.PI/2 से भी/थोड़ा/थोड़ा है तो मैं इसे मूल रूप से गणना करने दूंगा, लेकिन इसमें विशेष मामला जहां यह बिल्कुल मठ है। पीआई/2 या इसके गुणक में से एक, मैं इसे बिल्कुल शून्य होना चाहता हूं। कुछ सीमित परीक्षणों ने दिखाया है कि यह कम से कम मेरे कंप्यूटर पर काम करता है। क्या यह तर्क ठीक है, या क्या मुझे अभी भी एक सीमा की जांच करनी चाहिए? – dimo414

2

जब आप शुरू कर रहे हैं तो यह एक आम त्रुटि है, इस लिंक के कारणों की एक बहुत ही तकनीकी चर्चा है। http://docs.sun.com/source/806-3568/ncg_goldberg.html

लेकिन यह सरलतम रूप है में, एक ही रास्ता है कि हम वास्तव में दशमलव प्रणाली में 1/3 का प्रतिनिधित्व नहीं कर सकते में, वहाँ मानों बाइनरी सिस्टम में ठीक वैसे ही प्रदर्शित नहीं किया जा सकता हैं

संबंधित मुद्दे