पायथन राउंड 10 की अगली उच्चतम शक्ति के लिए


44

मैं ऐसा प्रदर्शन करने का प्रबंधन कैसे करूंगा math.ceilकि कोई संख्या 10 की अगली उच्चतम शक्ति को सौंपी जाए?

# 0.04  ->  0.1
# 0.7   ->  1
# 1.1   ->  10  
# 90    ->  100  
# ...

मेरा वर्तमान समाधान एक शब्दकोश है जो इनपुट नंबर की सीमा की जांच करता है, लेकिन यह हार्डकोड है और मैं एक-लाइनर समाधान पसंद करूंगा। हो सकता है कि मुझे एक साधारण गणितीय ट्रिक या एक समान संख्या में फंक्शन याद आ रहा हो?


3
@ बॉल्ड 10ऊपर से उन समाधानों की तरह काम करता है , यह उदाहरण के साथ कुछ की आवश्यकता होगी log10
जोंशरशेप

3
आपको जो शब्द चाहिए वह है "शक्ति"। हो सकता है कि आपको अपनी मूल भाषा के शब्द के लिए गलत अनुवाद मिल गया हो।
user2357112

धन्यवाद, मोनिका! @ बॉल्ड: मुझे यह सवाल मिला, लेकिन यह एक अलग समस्या है। जोनरशेप ने एक सही जवाब दिया है
ऑफ्टेलऑफेल

2
यह भी परिमाण के क्रम से संबंधित है । १ है ० वाँ क्रम, १० १ क्रम है, १००
वाँ

जवाबों:


60

आप ऐसा करने math.ceilके math.log10लिए उपयोग कर सकते हैं :

>>> 10 ** math.ceil(math.log10(0.04))
0.1
>>> 10 ** math.ceil(math.log10(0.7))
1
>>> 10 ** math.ceil(math.log10(1.1))
10
>>> 10 ** math.ceil(math.log10(90))
100

log10(n)आपको समाधान देता है xजो संतुष्ट करता है 10 ** x == n, इसलिए यदि आप xइसे राउंड अप करते हैं तो यह आपको 10 की अगली उच्चतम शक्ति के लिए घातांक देता है।

ध्यान दें कि एक मान के लिए nजहां xपहले से ही एक पूर्णांक है, "10 की अगली सर्वोच्च शक्ति" होगी n:

>>> 10 ** math.ceil(math.log10(0.1))
0.1
>>> 10 ** math.ceil(math.log10(1))
1
>>> 10 ** math.ceil(math.log10(10))
10

1
लॉग फ़ंक्शन के साथ काम करने पर लगता है कि मैं सिर्फ ट्रिक के साथ नहीं आ सका। मेरा मानना ​​है कि यह वही है जो मैं उम्मीद कर रहा था! बहुत बहुत धन्यवाद
offeltoffel

2
NB: आपके इच्छित व्यवहार के आधार पर, यह 10 की शक्तियों के लिए काम नहीं करता है, उदाहरण के लिए 10 ** math.ceil(math.log10(1)) == 1, जो "अगली सर्वोच्च शक्ति" नहीं है
Cireo

5
नोट: यह उत्तर फ्लोटिंग पॉइंट अंकगणित पर निर्भर करता है और जैसे कि यह राउंडिंग त्रुटियों के कारण विफल हो सकता है। उदाहरण के लिए 1000000000000001 में फीड करने का प्रयास करें।
प्लग

2
@plugwash आवश्यक नहीं है, गणित कार्य भी जैसे दशमलव। स्वीकार करेंगे।
जोंशरशेप

5
हां आप अन्य प्रकार पास कर सकते हैं, लेकिन वे एक डबल सटीक फ़्लोटिंग पॉइंट नंबर में परिवर्तित हो जाएंगे और C "log10" फ़ंक्शन में पास हो जाएंगे। बड़ी संख्या के लॉग को रोकने के लिए एक विशेष मामला है, लेकिन गोलाई की त्रुटियों को रोकने के लिए कुछ भी नहीं।
प्लग

21

आपकी समस्या को अंडर-निर्दिष्ट किया गया है, आपको वापस कदम रखने और कुछ प्रश्न पूछने की आवश्यकता है।

  • आपके इनपुट किस प्रकार के हैं?
  • आप अपने आउटपुट के लिए क्या प्रकार चाहते हैं?
  • 1 से कम परिणामों के लिए, आप वास्तव में क्या चाहते हैं? क्या आप 10 की वास्तविक शक्तियों या 10 की शक्तियों के फ्लोटिंग पॉइंट सन्निकटन चाहते हैं? आप जानते हैं कि 10 की नकारात्मक शक्तियाँ फ्लोटिंग पॉइंट में बिल्कुल व्यक्त नहीं की जा सकती हैं? चलो अब मान लेते हैं कि आप 10 की शक्तियों के फ्लोटिंग पॉइंट सन्निकटन चाहते हैं।
  • यदि इनपुट बिल्कुल 10 की शक्ति है (या 10 की शक्ति का निकटतम फ्लोटिंग पॉइंट सन्निकटन), तो क्या आउटपुट इनपुट के समान होना चाहिए? या यह 10 अप की अगली शक्ति होनी चाहिए? "10 -> 10" या "10 -> 100"? अब पूर्व के लिए मान लेते हैं।
  • क्या आपके इनपुट मान प्रश्न के प्रकारों का कोई संभावित मूल्य हो सकता है? या वे अधिक विवश हैं।

एक अन्य उत्तर में यह लघुगणक लेने का प्रस्ताव किया गया था, फिर राउंड अप (सीलिंग फंक्शन), फिर एक्सप्रेशन किया गया।

def nextpow10(n):
    return 10 ** math.ceil(math.log10(n))

दुर्भाग्य से यह गोलाई त्रुटियों से ग्रस्त है। सबसे पहले n जो भी डेटा टाइप होता है उससे डबल सटीक फ़्लोटिंग पॉइंट नंबर, संभावित रूप से राउंडिंग एरर को शुरू करने से परिवर्तित किया जाता है, फिर लॉगरिदम की गणना की जाती है, जो संभवतः अपने आंतरिक गणना और इसके परिणाम दोनों में अधिक राउंडिंग त्रुटियों को पेश करता है।

जैसे कि मुझे एक उदाहरण खोजने में देर नहीं लगी, जहां इसने गलत परिणाम दिया।

>>> import math
>>> from numpy import nextafter
>>> n = 1
>>> while (10 ** math.ceil(math.log10(nextafter(n,math.inf)))) > n:
...     n *= 10
... 
>>> n
10
>>> nextafter(n,math.inf)
10.000000000000002
>>> 10 ** math.ceil(math.log10(10.000000000000002))
10

दूसरी दिशा में विफल होना सैद्धांतिक रूप से भी संभव है, हालांकि यह भड़काने के लिए बहुत कठिन प्रतीत होता है।

इसलिए फ्लोट और किलों के लिए एक मजबूत समाधान के लिए हमें यह मानने की आवश्यकता है कि हमारे लघुगणक का मूल्य केवल अनुमानित है, और इसलिए हमें कुछ संभावनाओं का परीक्षण करना चाहिए। की तर्ज पर कुछ

def nextpow10(n):
    p = round(math.log10(n))
    r = 10 ** p
    if r < n:
        r = 10 ** (p+1) 
    return r;

मेरा मानना ​​है कि इस कोड को सभी समझदार वास्तविक दुनिया के परिमाणों में सभी तर्कों के लिए सही परिणाम देना चाहिए। यह बहुत छोटे या बहुत बड़ी संख्या में गैर पूर्णांक और गैर-फ़्लोटिंग बिंदु प्रकारों के कारण टूट जाएगा क्योंकि उन्हें फ़्लोटिंग पॉइंट में परिवर्तित किया जा सकता है। अजगर विशेष मामलों में अतिप्रवाह को रोकने के प्रयास में लॉग 10 फ़ंक्शन के लिए पूर्णांक तर्क देता है, लेकिन फिर भी पर्याप्त रूप से बड़े पैमाने पर पूर्णांक के साथ गोलाई त्रुटियों के कारण गलत परिणामों को मजबूर करना संभव हो सकता है।

दो कार्यान्वयन का परीक्षण करने के लिए मैंने निम्नलिखित परीक्षण कार्यक्रम का उपयोग किया।

n = -323 # 10**-324 == 0
while n < 1000:
    v = 10 ** n
    if v != nextpow10(v): print(str(v)+" bad")
    try:
        v = min(nextafter(v,math.inf),v+1)
    except:
        v += 1
    if v > nextpow10(v): print(str(v)+" bad")
    n += 1

यह भोले-भाले क्रियान्वयन में बहुत सारी विफलताएं पाता है, लेकिन बेहतर क्रियान्वयन में कोई नहीं।


यहाँ अधिक विस्तार में जाने के आपके प्रयास के लिए धन्यवाद। हालांकि जोंशरशेप के जवाब ने मेरी समस्या को पहले ही हल कर दिया है, यह उत्तर दूसरों के लिए समान लेकिन अधिक विशिष्ट प्रश्नों के लिए उपयोगी हो सकता है।
offeltoffel

1
roundइसके बजाय आप का उपयोग क्यों करते हैं math.ceil? यह बहुत सारे अनावश्यक मामलों को पेश करेगा जहां r < nयह सच है और इसलिए इसे अतिरिक्त काम करने की आवश्यकता है।
a_guest

1
क्योंकि लॉग किसी भी दिशा में बंद हो सकता है।
प्लग

1
"इम्प्रूव्ड" कोड का उपयोग करते हुए, लेकिन गणित के द्वारा बदल दिया गया। रिलिज फेल होने पर 1e-317 के लिए परिणाम कम अंत में और 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007000000000000007000000000000000700000000000000700000000007000700000000000070000007000000700000070000007 के लिए भुगतान किया गया।
प्लगवॉश

1
(व्यवहार में यह शायद ठीक है)
प्लग

3

ऐसा लगता है कि आप 10 की सबसे कम अगली शक्ति चाहते हैं ... यहां शुद्ध गणित और लॉग का उपयोग करने का एक तरीका है, लेकिन पुनरावृत्ति।

def ceiling10(x):
    if (x > 10):
        return ceiling10(x / 10) * 10
    else:
        if (x <= 1):
            return ceiling10(10 * x) / 10
        else:
            return 10
for x in [1 / 1235, 0.5, 1, 3, 10, 125, 12345]:
    print(x, ceiling10(x))

बस इस एक का परीक्षण किया, मैं इसे एक उत्थान दे रहा हूं क्योंकि यह सबसे व्यावहारिक मामलों में अच्छी तरह से काम करता है, लेकिन यह पर्याप्त रूप से छोटे इनपुट के साथ गोलाई त्रुटियों से पीड़ित लगता है। छत 10 (1e-6) 1.0000000000000002e-06 देता है
प्लग

0
y = math.ceil(x)
z = y + (10 - (y % 10))

कुछ इस तरह शायद? यह मेरे सिर के ठीक ऊपर है, लेकिन जब मैंने टर्मिनल में कुछ संख्याओं की कोशिश की तो यह काम कर गया।


0

इसकी जांच करें!

>>> i = 0.04123; print i, 10 ** len( str( int( i ) ) ) if int( i ) > 1  else 10 if i > 1.0 else 1 if i > 0.1 else  10 ** ( 1 - min( [ ("%.100f" % i ).replace('.','').index( k ) for k in [ str( j ) for j in xrange( 1, 10 ) if str( j ) in "%.100f" % i  ] ]  ) )               
0.04123 0.1
>>> i = 0.712; print i, 10 ** len( str( int( i ) ) ) if int( i ) > 1  else 10 if i > 1.0 else 1 if i > 0.1 else  10 ** ( 1 - min( [ ("%.100f" % i ).replace('.','').index( k ) for k in [ str( j ) for j in xrange( 1, 10 ) if str( j ) in "%.100f" % i  ] ]  ) )                 
0.712 1
>>> i = 1.1; print i, 10 ** len( str( int( i ) ) ) if int( i ) > 1  else 10 if i > 1.0 else 1 if i > 0.1 else  10 ** ( 1 - min( [ ("%.100f" % i ).replace('.','').index( k ) for k in [ str( j ) for j in xrange( 1, 10 ) if str( j ) in "%.100f" % i  ] ]  ) )                   
1.1 10
>>> i = 90; print i, 10 ** len( str( int( i ) ) ) if int( i ) > 1  else 10 if i > 1.0 else 1 if i > 0.1 else  10 ** ( 1 - min( [ ("%.100f" % i ).replace('.','').index( k ) for k in [ str( j ) for j in xrange( 1, 10 ) if str( j ) in "%.100f" % i  ] ]  ) )                    
90 100

यह कोड दस की शक्ति के मूलधन पर आधारित है len( str( int( float_number ) ) )

4 मामले हैं:

    1. int( i ) > 1

    Floatसंख्या - में परिवर्तित int, इसके बाद से स्ट्रिंग str(), हमें एक stringसाथ देगा, lengthजिसे हम बिल्कुल देख रहे हैं। तो, पहला भाग, इनपुट के लिए i > 1.0- यह 10इस लंबाई की शक्ति में दस है।

    1. & 3. लिटिल ब्रांचिंग: i > 1.0और i > 0.1<=> यह क्रमशः 10और 1है।
    1. और आखिरी मामला, जब i < 0.1: यहां, दस नकारात्मक शक्ति में होंगे। अल्पविराम के बाद पहला गैर शून्य तत्व प्राप्त करने के लिए, मैंने ऐसे निर्माण का उपयोग किया है ("%.100f" % i ).replace('.','').index( k ), जहां कश्मीर [1:10]अंतराल पर चलता है। तत्पश्चात, न्यूनतम परिणाम सूची लें। और एक की कमी, यह पहले शून्य है, जिसे गिना जाएगा। इसके अलावा, यहां मानक अजगर index()दुर्घटनाग्रस्त हो सकता है, अगर यह [1:10]अंतराल से कम से कम गैर-शून्य तत्व नहीं पाएगा , यही कारण है कि अंत में मुझे घटना द्वारा "फ़िल्टर" लिस्टिंग करना होगा if str( j ) in "%.100f" % i:। इसके अतिरिक्त, सटीक सटीक प्राप्त करने के लिए - %.100fअलग-अलग लिया जा सकता है।

कृपया कुछ स्पष्टीकरण जोड़ें।
मोबिन रंजबार
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.