स्पष्ट रूप से java.lang.StrictMath
में अतिरिक्त फ़ंक्शन (हाइपरबोलिक्स इत्यादि) शामिल हैं जो java.lang.Math
नहीं है, लेकिन क्या दोनों पुस्तकालयों में पाए जाने वाले कार्यों में कोई अंतर है?java.lang.Math और java.lang.StrictMath के बीच क्या अंतर है?
उत्तर
Math
वर्ग के लिए जावाडोक कुछ दो वर्गों के बीच मतभेद के बारे में जानकारी प्रदान करता है:
वर्ग
StrictMath
के संख्यात्मक तरीकों के कुछ विपरीत, सभी कार्यान्वयनMath
के समकक्ष कार्यों के बिट-बिट-बिट परिणामों को वापस करने के लिए परिभाषित नहीं किया गया है। यह छूट बेहतर प्रदर्शन करता है कार्यान्वयन जहां सख्त पुनरुत्पादन की आवश्यकता नहीं है।डिफ़ॉल्ट
Math
तरीकों सिर्फ अपने कार्यान्वयन के लिएStrictMath
में बराबर विधि कॉल के कई द्वारा। कोड जनरेटर प्लेटफ़ॉर्म-विशिष्ट देशी पुस्तकालयों या माइक्रोप्रोसेसर निर्देश, जहां उपलब्ध,Math
तरीकों में से उच्च प्रदर्शन कार्यान्वयन प्रदान करने के लिए उपयोग करने के लिए प्रोत्साहित किया जाता है। इस तरह के उच्च प्रदर्शन कार्यान्वयन अभी भीMath
के लिए विनिर्देश के अनुरूप होना चाहिए।
इसलिए, Math
वर्ग क्या निश्चित संचालनों के लिए क्या करना चाहिए के बारे में कुछ नियम बाहर देता है, लेकिन वे मांग नहीं है कि सटीक ही परिणाम पुस्तकालयों के सभी कार्यान्वयन में वापस लौटा दिया।
यह पुस्तकालयों के विशिष्ट कार्यान्वयन के लिए समान वापसी के लिए अनुमति देता है, लेकिन सटीक उसी परिणाम नहीं, उदाहरण के लिए, Math.cos
कक्षा कहा जाता है। यह प्लेटफॉर्म-विशिष्ट कार्यान्वयन (जैसे कि x86 फ़्लोटिंग पॉइंट और कहें, SPARC फ़्लोटिंग पॉइंट का उपयोग करके) के लिए अनुमति देगा जो विभिन्न परिणामों को वापस कर सकता है।
StrictMath
साथ
हालांकि, (मंच-विशिष्ट कार्यान्वयन के कुछ उदाहरण के लिए विकिपीडिया में Sine लेख के Software Implementations अनुभाग देखें।), विभिन्न कार्यान्वयन द्वारा लौटाए गए परिणाम ही परिणाम लौटना चाहिए । यह उन उदाहरणों के लिए वांछनीय होगा जहां विभिन्न प्लेटफार्मों पर परिणामों की पुनरुत्पादन की आवश्यकता होती है।
लेकिन अलग-अलग प्लेटफ़ॉर्म-विशिष्ट कार्यान्वयन अलग-अलग परिणाम क्यों उत्पन्न करना चाहते हैं? कोसाइन सार्वभौमिक रूप से परिभाषित नहीं है? – Aivar
@ आइवर: 'मठ' वर्ग से उद्धरण में सूचीबद्ध कारणों के लिए - विशिष्ट प्लेटफ़ॉर्म पर उपलब्ध देशी विधियों का लाभ उठाने के लिए, जो सॉफ़्टवेयर-आधारित समाधान का उपयोग करने से अधिक (कई मामलों में) होने की संभावना है जो सभी प्लेटफार्मों पर बिल्कुल वही उत्तर देने की गारंटी है। – coobird
ठीक है, तो इसका मतलब है कि कुछ प्लेटफार्मों ने बिट्स की दी गई मात्रा में फिट बैठने वाले सबसे सटीक उत्तर की गणना नहीं करना चुना है, लेकिन दक्षता के लिए परिशुद्धता का व्यापार किया है? और विभिन्न प्लेटफार्मों ने अलग-अलग व्यापार-बंद किए हैं? – Aivar
क्या आपने सोर्स कोड देखा था? java.lang.Math
में कई विधियां java.lang.StrictMath
पर दी गई हैं।
उदाहरण:
public static double cos(double a) {
return StrictMath.cos(a); // default impl. delegates to StrictMath
}
+1। जावा के लिए यह एक मजबूत बिंदु है .NET: जावा एपीआई जहाजों को स्रोत कोड का एक बड़ा हिस्सा जेडीके के साथ src.zip नामक फ़ाइल में। और अब डाउनलोड नहीं किया जा सकता है कि जेवीएम खुले खुले हैं। जावा स्रोत को पढ़ना समस्याओं को हल करने का सबसे विज्ञापित तरीका नहीं हो सकता है: यह एक बुरा विचार प्रतीत हो सकता है क्योंकि आपको आमतौर पर "सार्वजनिक इंटरफ़ेस का पालन करना और कार्यान्वयन नहीं करना चाहिए।" हालांकि, स्रोत को पढ़ने का एक मजबूत लाभ है: यह आपको हमेशा सत्य देगा। और कभी-कभी यह सभी की सबसे मूल्यवान चीज है। –
@ माइकक्लार्क आप .NET के लिए स्रोत भी पढ़ सकते हैं। –
@ एंड्रू टिप के लिए धन्यवाद। मैंने विजुअल स्टूडियो में इसे सेट अप करने के तरीके पर एक ट्यूटोरियल पढ़ना समाप्त कर दिया। जावा में अभी भी थोड़ा सा फायदा हो सकता है कि आप वीएम के लिए स्रोत कोड डाउनलोड कर सकते हैं, न केवल इसकी मानक लाइब्रेरी (ढांचा)। कोई बात नहीं धन्यवाद! –
@ntoskrnl जो कोई भी जेवीएम इंटर्नल्स के साथ काम कर रहा है, मैं आपकी राय को दूसरी बार देखना चाहता हूं कि "अंतर्निहित रूप से स्ट्रिक्टैथ विधियों के समान व्यवहार नहीं करते हैं"। इसे खोजने के लिए (या साबित), हम केवल एक साधारण परीक्षण लिख सकते हैं।
उदाहरण के लिए Math.pow
लें, java.lang.Math के लिए जावा कोड की जांच करें।पॉव (डबल एक, डबल ख), हम देखेंगे:
public static double pow(double a, double b) {
return StrictMath.pow(a, b); // default impl. delegates to StrictMath
}
लेकिन JVM, intrinsics या क्रम कॉल के साथ इसे लागू करने के लिए इस प्रकार लौटने परिणाम हम StrictMath.pow
से उम्मीद होती है क्या से अलग हो सकता है।
और निम्नलिखित कोड इस StrictMath.pow()
//Strict.java, testing StrictMath.pow against Math.pow
import java.util.Random;
public class Strict {
static double testIt(double x, double y) {
return Math.pow(x, y);
}
public static void main(String[] args) throws Exception{
final double[] vs = new double[100];
final double[] xs = new double[100];
final double[] ys = new double[100];
final Random random = new Random();
// compute StrictMath.pow results;
for (int i = 0; i<100; i++) {
xs[i] = random.nextDouble();
ys[i] = random.nextDouble();
vs[i] = StrictMath.pow(xs[i], ys[i]);
}
boolean printed_compiled = false;
boolean ever_diff = false;
long len = 1000000;
long start;
long elapsed;
while (true) {
start = System.currentTimeMillis();
double blackhole = 0;
for (int i = 0; i < len; i++) {
int idx = i % 100;
double res = testIt(xs[idx], ys[idx]);
if (i >= 0 && i<100) {
//presumably interpreted
if (vs[idx] != res && (!Double.isNaN(res) || !Double.isNaN(vs[idx]))) {
System.out.println(idx + ":\tInterpreted:" + xs[idx] + "^" + ys[idx] + "=" + res);
System.out.println(idx + ":\tStrict pow : " + xs[idx] + "^" + ys[idx] + "=" + vs[idx] + "\n");
}
}
if (i >= 250000 && i<250100 && !printed_compiled) {
//presumably compiled at this time
if (vs[idx] != res && (!Double.isNaN(res) || !Double.isNaN(vs[idx]))) {
System.out.println(idx + ":\tcompiled :" + xs[idx] + "^" + ys[idx] + "=" + res);
System.out.println(idx + ":\tStrict pow :" + xs[idx] + "^" + ys[idx] + "=" + vs[idx] + "\n");
ever_diff = true;
}
}
}
elapsed = System.currentTimeMillis() - start;
System.out.println(elapsed + " ms ");
if (!printed_compiled && ever_diff) {
printed_compiled = true;
return;
}
}
}
}
के खिलाफ बुला Math.pow()
मैं OpenJDK 8u5-B31 के साथ इस परीक्षण भाग गया और नीचे परिणाम मिला पता चलता है:
10: Interpreted:0.1845936372497491^0.01608930867480518=0.9731817015518033
10: Strict pow : 0.1845936372497491^0.01608930867480518=0.9731817015518032
41: Interpreted:0.7281259501809544^0.9414406865385655=0.7417808233050295
41: Strict pow : 0.7281259501809544^0.9414406865385655=0.7417808233050294
49: Interpreted:0.0727813262968815^0.09866028976654662=0.7721942440239148
49: Strict pow : 0.0727813262968815^0.09866028976654662=0.7721942440239149
70: Interpreted:0.6574309575966407^0.759887845481148=0.7270872740201638
70: Strict pow : 0.6574309575966407^0.759887845481148=0.7270872740201637
82: Interpreted:0.08662340816125613^0.4216580281197062=0.3564883826345057
82: Strict pow : 0.08662340816125613^0.4216580281197062=0.3564883826345058
92: Interpreted:0.20224488115245098^0.7158182878844233=0.31851834311978916
92: Strict pow : 0.20224488115245098^0.7158182878844233=0.3185183431197892
10: compiled :0.1845936372497491^0.01608930867480518=0.9731817015518033
10: Strict pow :0.1845936372497491^0.01608930867480518=0.9731817015518032
41: compiled :0.7281259501809544^0.9414406865385655=0.7417808233050295
41: Strict pow :0.7281259501809544^0.9414406865385655=0.7417808233050294
49: compiled :0.0727813262968815^0.09866028976654662=0.7721942440239148
49: Strict pow :0.0727813262968815^0.09866028976654662=0.7721942440239149
70: compiled :0.6574309575966407^0.759887845481148=0.7270872740201638
70: Strict pow :0.6574309575966407^0.759887845481148=0.7270872740201637
82: compiled :0.08662340816125613^0.4216580281197062=0.3564883826345057
82: Strict pow :0.08662340816125613^0.4216580281197062=0.3564883826345058
92: compiled :0.20224488115245098^0.7158182878844233=0.31851834311978916
92: Strict pow :0.20224488115245098^0.7158182878844233=0.3185183431197892
290 ms
कृपया ध्यान दें कि Random
लिए किया जाता है एक्स और वाई मान उत्पन्न करें, इसलिए आपका माइलेज रन से चलने के लिए अलग-अलग होगा। लेकिन अच्छी खबर यह है कि Math.pow
के संकलित संस्करण के परिणाम कम से कम Math.pow
के व्याख्या किए गए संस्करण से मेल खाते हैं। (ऑफ विषय: यहां तक कि इस स्थिरता को केवल ओपनजेडीके पक्ष से बग फिक्स की श्रृंखला के साथ लागू किया गया था।)
कारण?
ठीक है, ऐसा इसलिए है क्योंकि ओपनजेडीके जावा कोड को निष्पादित करने के बजाय Math.pow
(और अन्य गणित फ़ंक्शंस) को लागू करने के लिए इंट्रिनिक्स और रनटाइम फ़ंक्शंस का उपयोग करता है। मुख्य उद्देश्य x87 निर्देशों का लाभ उठाना है ताकि गणना के लिए प्रदर्शन को बढ़ाया जा सके। नतीजतन, StrictMath.pow
को रनटाइम पर Math.pow
से कभी भी नहीं कहा जाता है (ओपनजेडीके संस्करण के लिए जिसे हमने अभी उपयोग किया है, सटीक होने के लिए)।
और यह arragement Math
वर्ग के जावाडोक (भी ऊपर @coobird द्वारा उद्धृत) के अनुसार पूरी तरह से वैध है:
इस तरह के प्राथमिक घातीय, लघुगणक के रूप में कक्षा गणित बुनियादी सांख्यिक ऑपरेशनों को करने के तरीकों में शामिल है, वर्ग रूट, और त्रिकोणमितीय कार्यों।
कक्षा स्ट्रिक्टैथ के कुछ संख्यात्मक तरीकों के विपरीत, वर्ग गणित के समकक्ष कार्यों के सभी कार्यान्वयन को बिट-बिट-बिट परिणामों को वापस करने के लिए परिभाषित नहीं किया गया है। यह छूट बेहतर प्रदर्शन करने वाले कार्यान्वयन की अनुमति देती है जहां सख्त पुनरुत्पादन की आवश्यकता नहीं होती है।
डिफ़ॉल्ट रूप से कई गणित विधियों को उनके कार्यान्वयन के लिए स्ट्रिक्टैथ में समकक्ष विधि को कॉल करें। कोड जेनरेटर को मैथ विधियों के उच्च-प्रदर्शन कार्यान्वयन प्रदान करने के लिए, जहां उपलब्ध हो, प्लेटफार्म-विशिष्ट देशी पुस्तकालयों या माइक्रोप्रोसेसर निर्देशों का उपयोग करने के लिए प्रोत्साहित किया जाता है। इस तरह के उच्च प्रदर्शन कार्यान्वयन अभी भी गणित के लिए विनिर्देश के अनुरूप होना चाहिए।
और निष्कर्ष? खैर, जावा जैसी गतिशील कोड जनरेशन वाली भाषाओं के लिए, कृपया सुनिश्चित करें कि 'स्थिर' कोड से आप जो देखते हैं वह रनटाइम पर निष्पादित किया जाता है। आपकी आंखें कभी-कभी आपको वास्तव में गुमराह कर सकती हैं।
java.lang.Math का हवाला देते हुए:
फ्लोटिंग प्वाइंट
Math
तरीकों ulps, अंतिम स्थान पर इकाइयों के संदर्भ में मापा जाता है की यथार्थता।
...
यदि किसी विधि में हमेशा 0.5 अल्प्स से कम त्रुटि होती है, तो विधि हमेशा सटीक परिणाम के निकट फ़्लोटिंग-पॉइंट नंबर लौटाती है; इस तरह के एक विधि सही ढंग से गोल है। एक सही गोलाकार विधि आमतौर पर सबसे अच्छा एक फ़्लोटिंग-पॉइंट अनुमानित हो सकता है; हालांकि, यह कई फ़्लोटिंग-पॉइंट विधियों के लिए सही ढंग से गोलाकार होने के लिए अव्यवहारिक है।
और फिर हम Math.pow(..) के तहत देखते हैं, उदाहरण के लिए:
गणना परिणाम सटीक परिणाम के 1 ULP भीतर होना चाहिए।
अब, क्या ULP है? जैसी उम्मीद थी, java.lang.Math.ulp(1.0)
2.220446049250313e -16, जो 2 -52 है देता है। (इसके अलावा Math.ulp(8)
Math.ulp(10)
और Math.ulp(15)
, लेकिन नहीं Math.ulp(16)
रूप में एक ही मूल्य देता है।) दूसरे शब्दों में, हम अपूर्णांश के अंतिम बिट के बारे में बात कर रहे हैं।
तो, परिणाम java.lang.Math.pow(..)
द्वारा दिया, अपूर्णांश 52 बिट्स के अंतिम में गलत हो सकता है के रूप में हम टोनी गुआन के जवाब में इस बात की पुष्टि कर सकते हैं।
यह तुलना करने के लिए कुछ ठोस 1 ULP और 0.5 ULP कोड की खुदाई करने के लिए अच्छा होगा। मैं अटकलें चल जाएगा कि काफी अतिरिक्त काम का एक बहुत कुछ है कि पिछले बिट इसी कारण यह है कि अगर हम जानते हैं कि दो नंबर ए और बी 52 महत्वपूर्ण आंकड़े को गोल के लिए सही पाने के लिए आवश्यक है और हम जानते हैं करने के लिए एक × बी 52 महत्वपूर्ण आंकड़े को सही इच्छा , सही गोलाकार के साथ, वास्तव में हमें ए × बी के अंतिम बिट को प्राप्त करने के लिए ए और बी के कुछ अतिरिक्त बिट्स जानने की आवश्यकता है। लेकिन इसका मतलब है कि हमें युगल में मजबूर करके मध्यवर्ती परिणाम ए और बी को गोल नहीं करना चाहिए, हमें मध्यवर्ती परिणामों के लिए प्रभावी रूप से व्यापक प्रकार की आवश्यकता है। (मैंने जो देखा है, गणितीय कार्यों के अधिकांश कार्यान्वयन हार्ड-कोड किए गए प्रीकंप्यूटेड गुणांक वाले गुणाओं पर भारी निर्भर करते हैं, इसलिए यदि उन्हें डबल से अधिक व्यापक होने की आवश्यकता है, तो बड़ी दक्षता हिट होती है।)
- 1. # {} $ {} और% {} के बीच क्या अंतर है?
- 2. [अपरिभाषित] और [,] के बीच क्या अंतर है?
- 3. $ और $$ के बीच क्या अंतर है?
- 4. के बीच क्या अंतर है:। और: आर !?
- 5. भिन्नता और '-' के बीच क्या अंतर है?
- 6. "$^एन" और "$ +" के बीच क्या अंतर है?
- 7. java.lang.Math class
- 8. के बीच क्या अंतर है?
- 9. अंतर और कहां के बीच क्या अंतर है?
- 10. file_get_contents और fread बीच क्या अंतर है
- 11. क्या बीच का अंतर है :: और ::: स्काला
- 12. "। +" और "। +?" के बीच अंतर
- 13. $ {} और # {} के बीच अंतर क्या हैं?
- 14. PHP के बीच क्या अंतर है और इसमें शामिल है?
- 15. अपवाद के .TOString() और मैसेज के बीच क्या अंतर है?
- 16. 7zip के 7z.sfx और 7zsd.sfx के बीच क्या अंतर है?
- 17. डीएल के फाइलवर्सन और उत्पादवर्जन के बीच क्या अंतर है?
- 18. UIImageView के फ्रेम और सीमाओं के बीच क्या अंतर है?
- 19. फ़ायरबग के console.log() और console.debug() के बीच क्या अंतर है?
- 20. पैरामीटर परिभाषाओं के बीच अंतर (प्रकार और नाम), और (प्रकार * नाम) के बीच अंतर क्या हैं?
- 21. ओरिएंटब संस्करणों के बीच क्या अंतर है?
- 22. एन्कोड/डीकोड के बीच क्या अंतर है?
- 23. os.popen() विधियों के बीच क्या अंतर है?
- 24. MATLAB में & &&& के बीच क्या अंतर है?
- 25. ऑब्जेक्ट और * के बीच अंतर?
- 26. इन कार्यों के बीच क्या अंतर है?
- 27. applicationDidReceiveMemoryWarning, didReceiveMemoryWarning के बीच क्या अंतर है?
- 28. इन कार्यों के बीच क्या अंतर है
- 29. window.innerWidth window.outerWidth के बीच क्या अंतर है?
- 30. Response.Write() औरResponse.Output.Write() के बीच क्या अंतर है?
इस प्रश्न का पूरी तरह उत्तर दिया गया है जावाडोक – EJP
@EJP - मेरा मानना है कि, एसओ पर, आरटीएफएम कभी भी अच्छा जवाब नहीं है। जावा स्रोत कोड पढ़ने के लिए – ripper234