2010-11-24 23 views
7

में तर्कसंगत है या नहीं, तो मैं जांचने का एक अच्छा तरीका जानना चाहता हूं कि कोई संख्या x तर्कसंगत है (दो पूर्णांक n, m मौजूद है ताकि x = n/m) पायथन में हो।जांचें कि कोई संख्या पाइथन

mathematica में, इस समारोह

Rationalize[6.75] 
27/4 

द्वारा किया जाता है मुझे लगता है इस सवाल का एक दिया सटीकता के लिए एक जवाब है। क्या इन दो पूर्णांक प्राप्त करने का कोई आम एल्गोरिदम है?

उत्तर

13

अजगर> = 2.6 में तैरता पर एक as_integer_ratio विधि है: जिस तरीके तैरता प्रोग्रामिंग भाषाओं में परिभाषित कर रहे हैं करने के लिए

>>> a = 6.75 
>>> a.as_integer_ratio() 
(27, 4) 
>>> import math 
>>> math.pi.as_integer_ratio() 
(884279719003555, 281474976710656) 

हालांकि, कोई अपरिमेय संख्याओं हैं।

+0

इरेशनल्स को अनुपात (नाल) द्वारा प्रतिनिधित्व नहीं किया जा सकता है - यह कि बहुत परिभाषा और नाम का स्रोत है! – delnan

+0

@ डेलनान, एफडब्ल्यूआईडब्ल्यू, उन्हें राशन के रूप में दर्शाया जा सकता है। औपचारिक रूप से ऐसा करने के लिए सामान्य उपयोग में दोनों विधियां (डेडेकेंड कट और कौची श्रृंखला) ऐसा करने के लिए राशन का उपयोग करती हैं। वे सिर्फ एक अनंत राशि का उपयोग करते हैं :) – aaronasterling

+0

कुछ वास्तविक मज़ेदार निरंतर भिन्नताओं को देखने के लिए। स्वयं को एक समाधान लागू करने के लिए, आप निरंतर अंश करते हैं जब तक कि यह सटीक अंश न हो या आपके स्वाद के लिए denominator बहुत बड़ा हो जाए। – phkahler

4

हो सकता है यह आप के लिए दिलचस्प हो जाएगा: Best rational approximation

+0

+1 अच्छा लिंक के लिए यहाँ पायथन में एक काफी सरल कार्यान्वयन है। – martineau

5

एक परिमित दशमलव विस्तार के साथ कोई भी संख्या एक तर्कसंगत संख्या है। तुम हमेशा कह रही है कि यह

5195181354985216/1000000000000000 

से मेल खाती है तो बाद से तैरता और युगल परिमित परिशुद्धता वे सब परिमेय रहे है द्वारा उदाहरण

5.195181354985216 

के लिए हल कर सकता है।

+1

मूल प्रश्न में "दी गई सटीकता" नोट करें। –

1

जैसा कि आपने देखा है कि किसी भी फ़्लोटिंग पॉइंट नंबर को दशमलव बिंदु को स्थानांतरित करके दस की उचित शक्ति से विभाजित करके तर्कसंगत संख्या में परिवर्तित किया जा सकता है।

फिर आप लाभांश और विभाजक से सबसे बड़ा आम विभाजक निकाल सकते हैं और जांच सकते हैं कि इनमें से दोनों नंबर आपकी पसंद के डेटा प्रकार में फिट हैं या नहीं।

+0

एफडब्ल्यूआईडब्ल्यू, आप आसानी से 'fractions.gcd() 'का उपयोग कर पाइथन में सबसे बड़ा आम विभाजक निर्धारित कर सकते हैं। – martineau

4

पायथन तर्कसंगत संख्याओं के बजाय फ़्लोटिंग-पॉइंट प्रतिनिधित्व का उपयोग करता है। तर्कसंगत संख्याओं के बारे में कुछ विवरणों के लिए the standard library fractions module पर एक नज़र डालें।

का निरीक्षण करें, उदाहरण के लिए, इस, देखने के लिए कारण है कि यह गलत हो जाता है:

>>> from fractions import Fraction 
>>> 1.1 # Uh oh. 
1.1000000000000001 
>>> Fraction(1.1) # Will only work in >= Python 2.7, anyway. 
Fraction(2476979795053773, 2251799813685248) 
>>> Fraction(*1.1.as_integer_ratio()) # Python 2.6 compatible 
Fraction(2476979795053773, 2251799813685248) 

(ओह, तुम एक मामले में जहां यह काम करता है देखना चाहते हो?)

>>> Fraction('1.1') 
Fraction(11, 10) 
+0

क्या प्रोग्रामिंग भाषाएं हैं जो तर्कसंगत संख्याओं का उपयोग करती हैं? – SilentGhost

+2

@ सिलेंटगोस्ट: एबीसी करता है। इसके साथ ग्विडो के अनुभव देखें और क्यों पाइथन ऐसा नहीं करता है: http://python-history.blogspot.com/2009/03/problem-with-integer-division.html –

+0

@ सिलेंटगोस्ट, कॉमन लिस्प और (मुझे विश्वास है) योजना भी करते हैं। जाल को इंगित करने के लिए – aaronasterling

0

असली के साथ समस्या प्रोग्रामिंग भाषाओं में संख्या यह है कि उन्हें आमतौर पर एक सटीकता के रूप में एक सीमित प्रतिनिधित्व लौटने वाले कार्यों के रूप में परिभाषित किया जाता है (उदाहरण के लिए एक फ़ंक्शन जो तर्क के रूप में एन लेता है और 2^-n सटीकता के भीतर एक फ़्लोटिंग पॉइंट नंबर देता है)।

आप निश्चित रूप से एक तर्कसंगत/पूर्णांक को वास्तविक में बदल सकते हैं, लेकिन समानता के लिए वास्तविकताओं की तुलना करना भी अनिश्चित है (यह अनिवार्य रूप से रोकथाम की समस्या है)।

आप यह नहीं बता सकते कि वास्तविक संख्या x तर्कसंगत है: यहां तक ​​कि गणित में भी, यह आमतौर पर कठिन होता है, क्योंकि आपको पी और क्यू जैसे x = p/q मिलना पड़ता है, और यह अक्सर गैर रचनात्मक होता है।

हालांकि, एक सटीकता विंडो दी गई है, उदाहरण के लिए निरंतर अंश विस्तार के लिए आप इस सटीकता के लिए "सर्वश्रेष्ठ" तर्कसंगत अनुमान प्राप्त कर सकते हैं। मेरा मानना ​​है कि यह अनिवार्य रूप से गणित करता है। लेकिन आपके उदाहरण में, 6.75 पहले ही तर्कसंगत है। इसके बजाय पीआई के साथ प्रयास करें।

8

चल बिन्दु संख्या की प्रकृति का मतलब है कि यह जांच को कोई मतलब नहीं है एक फ्लोटिंग प्वाइंट संख्या तर्कसंगत है, के बाद से सभी चल बिन्दु संख्या वास्तव में प्रपत्र n/2 ई की भिन्न हैं। हालांकि, आप शायद यह जानना चाहें कि सरल अंश (2 की एक बड़ी शक्ति के बजाए एक छोटे से denominator के साथ) है जो किसी दिए गए फ़्लोटिंग-पॉइंट नंबर का बारीकी से अनुमान लगाता है।

डोनाल्ड Knuth में इस बाद की समस्या पर चर्चा करता है कंप्यूटर प्रोग्रामिंग की कला मात्रा II। 4.53-39 व्यायाम करने का उत्तर देखें। विचार श्रेणी के अंत बिंदुओं को निरंतर भिन्नताओं के रूप में विस्तारित करके, सीमा के अंत में सबसे कम मूल्य वाले अंश को खोजना है, जब तक कि उनके गुणांक बराबर हों, और फिर जब वे भिन्न हों, तो उनके बीच सबसे सरल मूल्य लें।

from fractions import Fraction 
from math import modf 

def simplest_fraction_in_interval(x, y): 
    """Return the fraction with the lowest denominator in [x,y].""" 
    if x == y: 
     # The algorithm will not terminate if x and y are equal. 
     raise ValueError("Equal arguments.") 
    elif x < 0 and y < 0: 
     # Handle negative arguments by solving positive case and negating. 
     return -simplest_fraction_in_interval(-y, -x) 
    elif x <= 0 or y <= 0: 
     # One argument is 0, or arguments are on opposite sides of 0, so 
     # the simplest fraction in interval is 0 exactly. 
     return Fraction(0) 
    else: 
     # Remainder and Coefficient of continued fractions for x and y. 
     xr, xc = modf(1/x); 
     yr, yc = modf(1/y); 
     if xc < yc: 
      return Fraction(1, int(xc) + 1) 
     elif yc < xc: 
      return Fraction(1, int(yc) + 1) 
     else: 
      return 1/(int(xc) + simplest_fraction_in_interval(xr, yr)) 

def approximate_fraction(x, e): 
    """Return the fraction with the lowest denominator that differs 
    from x by no more than e.""" 
    return simplest_fraction_in_interval(x - e, x + e) 

और यहाँ हैं कुछ परिणाम:

>>> approximate_fraction(6.75, 0.01) 
Fraction(27, 4) 
>>> approximate_fraction(math.pi, 0.00001) 
Fraction(355, 113) 
>>> approximate_fraction((1 + math.sqrt(5))/2, 0.00001) 
Fraction(377, 233) 
+0

+1। नाइटपिक: यह होना चाहिए "अगर x == y: वापसी x" होना चाहिए क्योंकि आप बंद अंतराल [x, y] पर विचार कर रहे हैं। –

+0

मैं ऐसा नहीं करता क्योंकि 'x' और 'y' को फ़्लोट किया जाना चाहिए जबकि फ़ंक्शन को' फ्रैक्शन 'वापस करना है। मुझे लगता है कि इस मामले में एक त्रुटि उठाना बेहतर है। –

+0

यह 'फ्रैक्शन (* x.as_integer_ratio())' वापस करने के लिए कुछ समझदारी करेगा, मुझे लगता है। –

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