2009-11-17 14 views
5

क्या इस कोड में कोई कमी है, जो java.lang.Math.round का एक तेज़ (और सही) संस्करण प्रतीत होता है?Math.round के तेज़ कार्यान्वयन?

public static long round(double d) { 

    if (d > 0) { 
     return (long) (d + 0.5d); 
    } else { 
     return (long) (d - 0.5d); 
    } 
} 

यह इस तथ्य का लाभ उठाता है कि, जावा में, लंबे दौर तक शून्य तक छोटा हो जाता है।

+2

@TrueWill: यदि यह ठीक से नामित एक फ़ंक्शन में अच्छी तरह से है ... क्या यह वाकई मायने रखता है? शायद यह गणित-गहन कार्यक्रम में उपयोग किया जा रहा है। – Sivvy

+0

यह दुर्लभ होगा कि आपको 1 से आसपास की विधि के लिए कुछ करने का एक तेज़ तरीका मिल जाएगा।0 मूल विधि के साथ 100% स्थिरता बनाए रखते हुए। – TofuBeer

+0

बिल्कुल एक माइक्रो-अनुकूलन है, और स्थानीय अर्थ में इसके लायक था। - लेकिन इन्हें सामान्य उपयोग के लिए अनुशंसित नहीं किया जाता है। – mrjbq7

उत्तर

15

कुछ special cases जो विधि हैंडल, जो आपके कोड को संभाल नहीं करता है में बनाया गया हैं। प्रलेखन से:

  • तो तर्क NaN है, परिणाम 0.
  • है तर्क नकारात्मक अनंत या किसी से कम या Integer.MIN_VALUE के मूल्य के बराबर मूल्य है, तो परिणाम मूल्य के बराबर है Integer.MIN_VALUE का।
  • यदि तर्क सकारात्मक अनंतता है या से अधिक कोई मान Integer.MAX_VALUE के मान के बराबर है, तो परिणाम Integer.MAX_VALUE के मान के बराबर है।
5

हां; आप अंडरफ्लो या अतिप्रवाह के लिए लेखांकन नहीं कर रहे हैं। व्यावहारिक रूप से बोलते हुए, यह आपके आवेदन के लिए कोई फर्क नहीं पड़ता।

3

मैं इस परीक्षण किया गया है, और वहाँ एक प्रमुख संभावित वापसी जो अभी तक यहाँ वर्णित नहीं किया गया है: आप rounding tie-breaking विधि बदल रहे हैं।

Math.round() "राउंड आधे अप" नियम लागू करता है, जबकि आपकी round() विधि "शून्य से आधा दूर" नियम लागू करती है।

उदाहरण के लिए:

  • Math.round(-0.5d) =>0L
  • Your.round(-0.5d) =>-1L

यह कर सकते हैं या आप के लिए एक समस्या नहीं हो सकता है, लेकिन आप को समझना चाहिए उपरोक्त विधि यह है कि Math.round() के लिए ड्रॉप-इन प्रतिस्थापन नहीं, NaN और अनंतता के विचारों के बाद भी पहले से ही रेखांकित किया गया है।

एक और प्रासंगिक सवाल: Rounding negative numbers in Java

प्रदर्शन का सवाल है, इसमें कोई शक नहीं है कि उपरोक्त विधि काफी तेजी Math.round() से है - यह बेतरतीब ढंग से उत्पन्न धनात्मक और ऋणात्मक मानों के लिए समय का लगभग 35% में चलता है। इस विधि को एक तंग लूप में कॉल करते समय यह एक सार्थक अनुकूलन हो सकता है। यह branch prediction का उपयोग कर सीपीयू की वजह से केवल सकारात्मक मान दिए जाने पर भी बेहतर (25% रनटाइम) बेहतर होता है।

Math.round() अंततः एक देशी JNI कॉल, जो प्रदर्शन अंतर का कारण हो सकता है द्वारा कार्यान्वित किया जाता। This Sun/Oracle bug बताता है कि j6u22 में शुद्ध-जावा संस्करण हो सकता है, लेकिन मैं j6u23 में कहां देख सकता हूं, और वास्तव में Math.round() मेरे परीक्षणों में j6u16 के समान प्रदर्शन करता है। मैंने अन्य संस्करणों पर परीक्षण नहीं किया है।

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