2010-10-03 8 views
7

कुछ यूनिट परीक्षण कोड जो मैं लिख रहा हूं, के हिस्से के रूप में, मैंने निम्न कार्य लिखा है। इसका उद्देश्य यह निर्धारित करना है कि 'ए' को 'बी' में गोल किया जा सकता है, भले ही 'ए' या 'बी' कितना सटीक हो।पायथन: सामान्य मामले में बी को गोल किया जा सकता है

def couldRoundTo(a,b): 
    """Can you round a to some number of digits, such that it equals b?""" 
    roundEnd = len(str(b)) 
    if a == b: 
     return True 
    for x in range(0,roundEnd): 
     if round(a,x) == b: 
      return True 
    return False 

यहाँ समारोह से कुछ उत्पादन है:

>>> couldRoundTo(3.934567892987, 3.9) 
True 
>>> couldRoundTo(3.934567892987, 3.3) 
False 
>>> couldRoundTo(3.934567892987, 3.93) 
True 
>>> couldRoundTo(3.934567892987, 3.94) 
False 

जहां तक ​​मेरा बता सकते हैं, यह काम करता है। हालांकि, मुझे इस पर भरोसा करने से डर है कि मुझे फ़्लोटिंग पॉइंट सटीकता से संबंधित मुद्दों का सही समझ नहीं है। क्या कोई मुझे बता सकता है कि क्या यह इस कार्य को लागू करने का एक उचित तरीका है? यदि नहीं, तो मैं इसे कैसे सुधार सकता हूं?

उत्तर

3

क्या कोई मुझे बता सकता है कि यह इस कार्य को लागू करने का एक उचित तरीका है?

यह निर्भर करता है।दिया गया फ़ंक्शन आश्चर्यजनक रूप से व्यवहार करेगा यदि bठीक एक मान के बराबर है जो आमतौर पर दशमलव-से-बाइनरी-फ्लोट रूपांतरण से सीधे प्राप्त किया जाएगा।

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

>>> print(0.1, 0.2/2, 0.3/3) 
0.1 0.1 0.1 
>>> couldRoundTo(0.123, 0.1) 
True 
>>> couldRoundTo(0.123, 0.2/2) 
True 
>>> couldRoundTo(0.123, 0.3/3) 
False 

यह विफल रहता है क्योंकि 0.1 और 0.2/2 (और round(0.123, 1)) की तुलना में एक अलग प्रतिनिधित्व में की 0.3/3 परिणाम गणना।

यदि नहीं, तो मैं इसे कैसे सुधार सकता हूं?

सामान्य नि: यदि आपके गणना विशेष रूप से किसी भी तरह से दशमलव अंक शामिल है, बस Decimal उपयोग करते हैं, सब हानिपूर्ण आधार -2 राउंड ट्रिपिंग से बचने के लिए।

from decimal import Decimal 

def roundable(a, b): 
    a = Decimal(str(a)) 
    b = Decimal(str(b)) 
    return a.quantize(b) == b 
+0

मुझे एहसास हुआ कि यह कहीं भी लागू किया गया था। मैं इसे स्वीकार कर रहा हूं क्योंकि क्वांटिज़ ठीक वही करता है जो मैं ढूंढ रहा हूं। धन्यवाद। – Wilduck

1

एक तरह से यह करने के लिए:

def could_round_to(a, b): 
    (x, y) = map(len, str(b).split('.')) 
    round_format = "%" + "%d.%df"%(x, y) 
    return round_format%a == str(b) 

सबसे पहले, हम पहले और x और y में दशमलव के बाद अंकों की संख्या ले। फिर, हम %x.yf जैसे प्रारूप का निर्माण करते हैं। फिर, हम प्रारूप स्ट्रिंग में a की आपूर्ति करते हैं।

>>> "%2.2f"%123.1234 
'123.12' 
>>> "%2.2f"%123.1264 
'123.13' 
>>> "%3.2f"%000.001 
'0.00' 

अब, बाकी सब कुछ तारों की तुलना कर रहा है।

+0

+1 चतुराई और मुझे कुछ मैंने पहले नहीं देखा है दिखाने के लिए:

विशेष रूप से, Decimal एक सहायक quantize कहा जाता है कि इस समस्या को तुच्छता आसान बना देता है भी शामिल है। – Wilduck

0

केवल बात यह है कि मैं से डर लगता है चल अंक के तार से रूपांतरण प्राप्त हो सकता फ्लोटिंग प्वाइंट शाब्दिक व्याख्या (http://docs.python.org/reference/lexical_analysis.html#floating-point-literals के रूप में) है। मुझे नहीं पता कि क्या कोई गारंटी है कि एक फ्लोटिंग पॉइंट शाब्दिक फ्लोटिंग-पॉइंट नंबर का मूल्यांकन करेगा जो दिए गए स्ट्रिंग के सबसे नज़दीक है। यह उल्लिखित अनुभाग विनिर्देश में जगह है जहां मैं ऐसी गारंटी की अपेक्षा करता हूं।

उदाहरण के लिए, जावा स्ट्रिंग अक्षर से अपेक्षा की जाने वाली चीज़ों के बारे में अधिक विशिष्ट है। Double.valueOf(String) के प्रलेखन से:

[...] [तर्क] हमेशा की तरह "कम्प्यूटरीकृत वैज्ञानिक संकेतन" में या एक सटीक हेक्साडेसिमल मान के रूप में एक सटीक दशमलव मूल्य का प्रतिनिधित्व माने जाते हैं; इस सटीक संख्यात्मक मूल्य तो धारणात्मक एक "असीम सटीक" बाइनरी मान रहा है कि उसके बाद आईईईई 754 फ्लोटिंग प्वाइंट गणित के सामान्य दौर करने वाली निकटतम शासन द्वारा डबल टाइप करने के लिए गोल में बदल जाती है [...]

जब तक आप पाइथन दस्तावेज में कहीं भी ऐसी गारंटी नहीं पा रहे हैं, तो आप केवल भाग्यशाली हो सकते हैं, क्योंकि कुछ पहले फ़्लोटिंग-पॉइंट लाइब्रेरीज़ (जिस पर पाइथन भरोसा कर सकता है) स्ट्रिंग को केवल एक फ़्लोटिंग-पॉइंट नंबर पर कनवर्ट कर सकता है, न कि उपलब्ध सर्वोत्तम ।

दुर्भाग्यवश, मुझे ऐसा लगता है कि न तो round, न ही float, न ही फ्लोटिंग पॉइंट साहित्यिक के लिए विनिर्देश आपको कोई उपयोगी गारंटी देता है।

0

यदि आप उद्देश्य का परीक्षण करना चाहते हैं तो round फ़ंक्शन लक्ष्य के चारों ओर होगा, तो आप सही हैं। अन्यथा (उद्देश्य क्या है?) यदि आप संदेह में हैं, तो आपको decimal मॉड्यूल

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

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