अन-राउंड फ्रैक्चर


22

जब आप एक अंश को दशमलव संख्या में परिवर्तित करते हैं और आप उस संख्या को संग्रहीत करना चाहते हैं, तो आपको अक्सर इसे राउंड करना होता है, क्योंकि आप केवल एक निश्चित मात्रा में मेमोरी का उपयोग करना चाहते हैं। मान लें कि आप केवल 5 दशमलव अंक स्टोर कर सकते हैं, फिर 5/3 1.6667 हो जाता है। यदि आप केवल 2 दशमलव अंक स्टोर कर सकते हैं तो यह 1.7 होगा (अब यह मानते हुए कि यह हमेशा 0 और 9.99 के बीच है ...)।

यदि आप अब 1.7 के साथ उस प्रक्रिया को उलटने की कोशिश करते हैं और आप अपना अंश वापस प्राप्त करना चाहते हैं, तो यह मुश्किल हो सकता है, क्योंकि आप जानते हैं कि 1.7 केवल एक गोल संख्या है। बेशक आप 17/10 की कोशिश कर सकते हैं, लेकिन यह 'सुरुचिपूर्ण' 5/3 की तुलना में एक 'बदसूरत' अंश है।

तो लक्ष्य अब अंश को सबसे कम हर बी के साथ a / b ढूंढ रहा है, जिसके परिणामस्वरूप गोल दशमलव संख्या सही ढंग से गोल होने पर होती है।

विवरण

इनपुट में 1 से 5 अंकों की संख्या के साथ एक स्ट्रिंग होती है जो 0 (सहित) और 10 के बीच होती है (एक के साथ शामिल नहीं)। ' पहले अंक के बाद। मान लीजिए कि nअंकों की संख्या को दर्शाता है। आउटपुट दो पूर्णांकों की एक सूची / सरणी [numerator, denominator]या एक तर्कसंगत डेटाटाइप होना चाहिए (आप अपना खुद का बना सकते हैं या अंतर्निहित उपयोग कर सकते हैं) जहां अंश गैर-ऋणात्मक है और भाजक धनात्मक है। अंश संख्यात्मक (हर) को इनपुट के बराबर होना चाहिए जब सही ढंग से nअंकों के लिए गोल किया जाए (जिसका अर्थ हैn-1 दशमलव बिंदु के बाद अंकों का हो) के ।

प्रतिबंध: केवल एक लूप स्टेटमेंट की अनुमति है। इसका मतलब है कि आप केवल एक ही लूपिंग स्टेटमेंट (जैसे forया whileया gotoआदि) और साथ ही कार्यात्मक लूप का उपयोग mapकर सकते हैंfold अपने पूरे कोड में जो किसी सूची / सरणी के प्रत्येक तत्व पर कोड लागू कर सकते हैं, लेकिन आप इसे 'दुरुपयोग' के लिए स्वतंत्र हैं। या पुनरावर्तन आदि का उपयोग करें

आपको एक फंक्शन लिखना चाहिए। यदि आपकी भाषा में फ़ंक्शन नहीं हैं (या यहां तक ​​कि अगर यह करता है), तो आप वैकल्पिक रूप से मान सकते हैं कि इनपुट एक चर (या स्टड के माध्यम से इनपुट) में संग्रहीत है और परिणाम प्रिंट करें या इसे एक फ़ाइल में लिखें। सबसे कम बाइट्स जीतती है।

गोलाई

राउंडिंग को 'पारंपरिक' राउंडिंग नियमों का पालन करना चाहिए, अर्थात यदि अंतिम अंक जो कट जाएगा, वह 5 या अधिक होगा, तो आप राउंड अप करेंगे, और आप किसी भी अन्य मामलों के लिए राउंड डाउन करेंगे, इसलिए जैसे:

४.५४ ९ ४ परिणाम देगा जब गोलाई

  • 1 अंक: 5
  • 2 अंक: 4.5
  • 3 अंक: 4.55
  • 4 अंक: 4.549

उदाहरण

कृपया निम्नलिखित परीक्षण मामलों और अन्य 'दिलचस्प' को शामिल करें:

Input 1.7     Output 5/3
Input 0.      Output 0/1
Input 0.001   Output 1/667
Input 3.1416  Output 355/113

1
लेकिन कार्यात्मक भाषाओं में लूप जैसी कोई चीज नहीं होती है। Haskell में दुश्मन उदाहरण repeatअपने तर्क की एक अनंत सूची बनाता है। मुझे लूप लगता है लेकिन इसमें वास्तव में O (1) की समय जटिलता है। लेकिन मुझे लगता है कि प्रत्येक मामले को व्यक्तिगत रूप से सॉर्ट करना कार्यात्मक भाषाओं की अनुमति नहीं देने से बेहतर है।
गर्वित हेकेलर

3
मुझे "लूप" की वर्तमान परिभाषा पसंद नहीं है। उदाहरण के लिए, पायथन में, इसके for n in numbers: f(g(n))बराबर है map(f, map(g, numbers))। कार्यात्मक संस्करण mapदो बार उपयोग करता है , क्या यह वास्तव में अस्वीकृत होना चाहिए?
बजे

1
@ मार्टिनबटनर मैंने उस मामले के बारे में बात की, जिसमें अस्पष्टता के कारण कार्यात्मक भाषाओं को अस्वीकार कर दिया जाएगा
गर्वित हेकेलर

1
मुझे खेद है कि मैं वास्तव में उस चर्चा में योगदान नहीं कर सकता क्योंकि कार्यात्मक प्रोग्रामिंग के बारे में मेरा ज्ञान मूल रूप से शून्य है। यदि आपके पास इसका कोई समाधान है, तो आप इस बारे में अनिश्चित हैं कि यह 'नियमों' का अनुपालन करता है या नहीं, कृपया इसे जमा करें! अंत में यह एक मजेदार और शैक्षिक चुनौती माना जाता है!
दोष

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

जवाबों:


4

CJam, 41 40 36 बाइट्स

Q'./1=,:L0\{;)_Qd*mo_d2$/LmOQd-}g'/@

Asuumes इनपुट स्ट्रिंग को Q में संग्रहीत किया जाता है, जिसे स्पष्ट रूप से प्रश्न द्वारा अनुमति दी जाती है। इसे ऑनलाइन आज़माएं।

परीक्षण के मामलों

$ for d in 1.7 0. 0.001 3.1416; do cjam <(echo "\"$d\":Q;
> Q'./1=,:L0\{;)_Qd*mo_d2$/LmOQd-}g'/@
> "); echo; done
5/3
0/1
1/667
355/113

यह काम किस प्रकार करता है

Q'./1=,:L  " Count the number of characters after the dot and store it in L.     ";
0\         " Push 0 (denominator) and swap it with L (dummy value).              ";
{          "                                                                     ";
  ;        " Discard the topmost item from the stack (numerator or dummy value). ";
  )        " Increment the denominator.                                          ";
  _Qd*mo   " Multiply a copy by Double(Q) and round.                             ";
  _d2$/    " Cast a copy to Double and it divide it by the denominator.          ";
  LmO      " Round to L digits.                                                  ";
  Qd       " If the result is not Double(Q),                                     ";
}g         " repeat the loop.                                                    ";
./@        " Push a slash and rotate the denominator on top of it.               ";

15

टी-एसक्यूएल 254

जबकि T-SQL वास्तव में इस तरह की चीज के अनुकूल नहीं है, यह कोशिश करने के लिए मज़ेदार है। प्रदर्शन वास्तविक बुरा उच्चतर हो जाता है। यह 1000 के एक भाजक तक सीमित है।

इनपुट एक फ्लोट चर है @

WITH e AS(SELECT *FROM(VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(0))n(n)),t AS(SELECT ROW_NUMBER()OVER(ORDER BY(SELECT \))N FROM e a,e b,e c,e d)SELECT TOP 1concat(n.n,'/',d.n)FROM t d,t n WHERE round(n.n/(d.n+.0),len(parsename(@,1)))=@ ORDER BY d.n,n.n

क्वेरी का टूटना

WITH                                      -- Start CTE(Common Table Expression)
 e AS(                                    --Create a set of 10 rows
   SELECT *
   FROM(VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(0))n(n)
 ),
 t AS(                                    
   SELECT ROW_NUMBER()OVER(ORDER BY(SELECT \))N 
   FROM e a,e b,e c,e d                   --Cross join e to produce 1000 numbered rows
 )
SELECT 
  TOP 1                                   --Grab first result
  concat(n.n,'/',d.n)                     --Build output
FROM t d,t n                              --Cross join t against itself for denominator and numerator
WHERE round(
  n.n/(d.n+.0),                           --Force float division with +.0
  len(parsename(@,1))                     --Get rounding length
  )=@                                     --Filter where the rounded result = input
ORDER BY d.n,n.n                          --Order by denominator then numerator

+1। मुझे यह पसंद है। मैंने डाला 3.14159और इसने मुझे विधिवत रूप से दिया355/113
टॉम चैंटलर

1
+1 मैंने यहां SQL भाषा देखने की कभी उम्मीद नहीं की थी !!!
दोष

@TomChantler मुझे संदेह है कि आप आखिरकार :)
मिकी

@flawr ईमानदार होने के लिए मुझे नहीं लगता था कि यह काम करने वाला था .. हालांकि बहुत बल बल विधि।
19

12

हास्केल, 62 59

यदि केवल नाम इतने लंबे समय तक नहीं थे ...

import Data.Ratio
f s=approxRational(read s)$50/10^length s

यह एक Rationalमान लौटाने वाला फ़ंक्शन है ।

स्पष्टीकरण: फ़ंक्शन approxRationalएक फ़ंक्शन है जो एक फ्लोट नंबर और एक फ्लोट एप्सिलॉन लेता है और सबसे सरल तर्कसंगत लौटाता है जो इनपुट की दूरी एप्सिलॉन में है। मूल रूप से, "क्षमा योग्य त्रुटि" दूरी में तर्कसंगत के लिए फ्लोट का सबसे सरल सन्निकटन लौटाता है।

आइए इस फ़ंक्शन का उपयोग हमारे उपयोग के लिए करें। इसके लिए हमें यह पता लगाना होगा कि दी गई संख्या तक राउंड फ़्लोट का क्षेत्र क्या है। तो इस approxRationalसमारोह में हो रही हमें जवाब मिल जाएगा।

उदाहरण के लिए, 1.7 कोशिश करते हैं। सबसे कम फ्लोट जो कि राउंड 1.7 से 1.65 है। कोई भी निचला 1.7 से गोल नहीं होगा। इसी तरह, तैरने की ऊपरी सीमा जो 1.7 के बराबर होती है, 1.75 होती है।
दोनों सीमाएँ हैं इनपुट संख्या +/- 0.05 हैं। यह आसानी से दिखाया जा सकता है कि यह दूरी हमेशा 5 * 10 ^ -(the length of the input - 1)(-1 है क्योंकि इनपुट में हमेशा एक '' होता है)। यहाँ से कोड काफी सरल है।

परीक्षण के मामलों:

*Main> map f ["1.7", "0.001", "3.1416"]
[5 % 3,1 % 667,355 % 113]

दुर्भाग्य से यह "0." पर काम नहीं करता है क्योंकि हास्केल का पार्सर फ़ंक्शन .फ्लोट के अंत में नहीं पहचाना जाता है । इस जगह से 5 बाइट्स के लिए निर्धारित किया जा सकता है read sके द्वारा read$s++"0"


यह एक दिलचस्प कार्य है। आमतौर पर इस तरह के कार्य सबसे अच्छे तर्कसंगत सन्निकटन को सबसे कम चरणों में एक संख्या में खोजने के उद्देश्य से मौजूद हैं, जो कि अलग-अलग निरंतर अंश निरूपणों का उपयोग करके सिद्ध होता है। वैकल्पिक रूप से, सबसे कम भाजक के साथ एक अंश ढूंढना अधिक शैक्षिक जिज्ञासा है। आमतौर पर एक मानक पुस्तकालय समारोह के रूप में इसे खोजने की उम्मीद नहीं की जाती है।
COTO

4
@ कोटो खैर, यह हास्केल है, यह अकादमिक अनुसंधान से भरा है।
हवलदार हेकेलर

7

रूबी, 127 125 बाइट्स

f=->n{b=q=r=(m=n.sub(?.,'').to_r)/d=10**p=n.count('0-9')-1
b=r if(r=(q*d-=1).round.to_r/d).round(p).to_f.to_s==n while d>1
b}

एक फ़ंक्शन को परिभाषित करता है fजो परिणाम को एक के रूप में लौटाता है Rational। जैसे अगर आप इस कोड को जोड़ते हैं

p f["1.7"]
p f["0."]
p f["0.001"]
p f["3.1416"]

आपको मिला

(5/3)
(0/1)
(1/667)
(355/113)

पाश हर पर खत्म हो गया है। मैं पूर्ण अंश से शुरू कर रहा हूं, उदाहरण 31416/10000के लिए अंतिम उदाहरण के लिए। फिर मैं भाजक को घटा रहा हूं, आनुपातिक रूप से अंश को घटाता हूं (और इसे गोल करता हूं)। यदि परिणामी परिमेय इनपुट संख्या के समान है, तो मुझे एक नया सबसे अच्छा अंश याद आ रहा है।


4

गणितज्ञ, ४ ९ ५३ पात्र

Rationalize[ToExpression@#,5 10^(1-StringLength@#)]&@

उपयोग:

Rationalize[ToExpression@#,5 10^(1-StringLength@#)]&@"1.7"

आउटपुट:

5/3

परीक्षण के मामलों:

input: 1.7     output: 5/3
input: 0.      output: 0
input: 0.001   output: 1/999
input: 3.1416  output: 355/113

0.001 केस ने मुझे अजीब समझा; जब तक यह 1/667 मामले में नहीं मिला, तब तक इसके विवरण के अनुसार तर्कसंगत कार्य नहीं किया गया था। यह सबसे छोटे भाजक के साथ संख्या को आउटपुट करना चाहिए जो निर्दिष्ट सीमा के भीतर है।


2
हाहा मैं सटीक एक ही समाधान का इस्तेमाल किया। हास्केल में यह बहुत लंबा है। btw, ऐसा नहीं लगता है कि आपका समाधान इनपुट के रूप में एक स्ट्रिंग लेता है जैसा कि कल्पना से आवश्यक है।
गौरवशाली हेकेलर

रुको, इनपुट एक स्ट्रिंग था? डांग, इसका मतलब है कि मैं कोड से कुछ सामान खींच सकता हूं।
टैली

आपके आउटपुट का 0.001मिलान OP से मेल नहीं खाता क्योंकि Rationalizeअवरोध को कम करने के लिए बाधा के अधीन नहीं है। जैसा कि मुझे गर्व हैकेलर पर उल्लेख किया गया है, हर को कम से कम करने के लिए एक तर्कसंगत सनसनीखेज फ़ंक्शन अत्यधिक गूढ़ है (संक्षेप में क्योंकि यह अनुमानित संख्या के लिए एक घटिया और अक्षम तरीका है)। मैं आमतौर पर एक मानक पुस्तकालय समारोह होने की उम्मीद नहीं करूंगा।
COTO

@ COTO डॉक्स के अनुसार यह हर को कम करता है
मार्टिन एंडर

@ मार्टिनबटनर: यह दिलचस्प है कि यह आउटपुट देता है 1/999। 999 केवल 1e-6 और 2e-6 के बीच त्रुटि के लिए (स्वीकार्य) सबसे कम भाजक बन जाता है। त्रुटि बाउंड स्पष्ट रूप से 5e-4 है। तो उस मामले में जो भी गणितज्ञ कर रहा है, वह निश्चित रूप से कल्पना करने के लिए काम नहीं कर रहा है। : पी
सीओटीओ

4

पायथन 2.7+, 111 वर्ण

सबूत है कि आप किसी भी भाषा में भयानक कोड लिख सकते हैं:

def f(s):
 t,e,y=float(s),50*10**-len(s),1;n=d=x=0
 while x|y:n,d=n+x,d+y;a=1.*n/d;x,y=a<t-e,a>t+e
 return n,d

उत्पादन

>>> [f(s) for s in ("1.7", "0.", "0.001", "3.1416")]
[(5, 3), (0, 1), (1, 667), (355, 113)]

3

एपीएल, ५०

2↑⍎⍕(⍎x←⍞){50>|(10*⍴x)×⍺-⍵÷⍨n←⌊.5+⍺×⍵:n ⍵⋄''}¨⍳1e5

जब तक आप गिनती नहीं करते evalऔर toStringछोरों के रूप में

व्याख्या

दृष्टिकोण 1 से 10000 से अधिक भाजक के रूप में पुनरावृत्त करना है और अंश की गणना करना है जो फ्लोट से सबसे निकटता से मेल खाता है, फिर जांचें कि क्या त्रुटि सीमा के भीतर है। अंत में, सभी अंशों में से सबसे छोटी जोड़ी का चयन करें।

(⍎x←⍞)स्क्रीन से स्ट्रिंग इनपुट लें, असाइन करें xऔर
⍳1e51 से 10000 तक एरे जेनरेट करें सरणी
{...}¨के प्रत्येक तत्व के लिए, इसके साथ फ़ंक्शन को कॉल करें (⍎x←⍞)और तर्क (लूप)

⍺×⍵गुणा तर्क
⌊.5+दौर बंद (0.5 जोड़ने फिर नीचे गोलाई से)
n←आवंटित करने के लिए n
⍺-⍵÷⍨सही तर्क से विभाजित, फिर बाएं तर्क से घटाना
(10*⍴x)×गुणा 10 से "की लंबाई की शक्ति के लिए x"
|लो निरपेक्ष मान
50>जांच करें कि कम से कम 50 (की लंबाई x2 अधिक है डीपी की संख्या की तुलना में, इसलिए 0.5 के बजाय 50 का उपयोग करें)
:n ⍵⋄'' यदि पिछला चेक सही है, तो nऔर सही तर्क की सरणी लौटाएं, अन्यथा खाली स्ट्रिंग लौटें।

⍎⍕ toStringऔर फिर evalसरणी में सभी संख्याओं का एक सरणी प्राप्त करने के लिए
2↑केवल पहले 2 तत्वों का चयन करें, जो कि पहला अंश-भाजक युग्म है


2

जीएनयू डीसी, 72 बाइट्स

नहीं छोरों - डीसी भी उन्हें नहीं है। इसके बजाय नियंत्रण एक एकल पूंछ-पुनरावर्ती मैक्रो से आता है - डीसी के लिए मुहावरेदार।

?dXAr^d2*sf*sq1sd0[ld1+sd]sD[r1+r]sN[dlf*ld/1+2/dlq>Ndlq<Dlq!=m]dsmxpldp

आउटपुट:

$ for n in 1.7 0. 0.001 3.1416; do echo "    n = $n:"; dc unround.dc <<< $n; done
    n = 1.7:
5
3
    n = 0.:
0
1
    n = 0.001:
1
667
    n = 3.1416:
355
113
$ 

ओह। इस उत्तर में आंशिक व्याख्या ।


2

गणितज्ञ, 111 वर्ण

f=Module[{a=0,b=1,k},While[Round[a/b,10^-(StringLength[#]-2)]!=(k=ToExpression)@#,If[N[a/b]>k@#,b++,a++]];a/b]&

वास्तव में बहुत आसान है, और मुझे नहीं लगता कि यह अन्य समाधानों के रूप में कहीं भी तेजी से रूपांतरित हो जाता है, क्योंकि अंश और हर केवल एक के बाद बढ़ता है। मैं ज्यादातर इसका आसान हल खोजना चाहता था। मुझे अन्य उत्तरों को देखना होगा और देखना होगा कि वहां क्या होशियार चीजें होती हैं।

उत्पादन

f/@{"1.7","0.0","0.001","3.1416","3.14"}
{5/3, 0, 1/667, 355/113, 22/7}

क्या यहाँ कोई पाई स्वीकृति दिवस मनाता है ?


नहीं, मैं केवल ताऊ सन्निकटन दिवस मना रहा हूं। = P लेकिन मैंने अभी देखा है कि | 355/113 - pi | <10 ^ -6 =)
11:25 बजे त्रुटिपूर्ण

2

एप्सस्क्रिप्ट,> 300 बाइट्स

मैं इसे एक ऐसी भाषा में करना चाहता था, जिसमें मूल रूप से आवश्यक प्रकार की गोलाई हो। बाहर जाता है Applescript बिल फिट बैठता है। फिर मैंने एनुम को देखा rounding as taught in school, और गोल्फिंग प्रयोजनों के लिए एप्लास्क्रिप्ट की स्पष्ट अक्षमता के बावजूद, इसका उपयोग करने का विरोध नहीं कर सका:

on u(q)
    set n to 0
    set d to 1
    set x to 0
    set AppleScript's text item delimiters to "."
    set f to 10 ^ (q's text item 2's length)
    repeat until x = q as real
        set x to (round n * f / d rounding as taught in school) / f
        if x < q then set n to n + 1
        if x > q then set d to d + 1
    end repeat
    return {n, d}
end u

log my u("1.7")
log my u("0.")
log my u("0.001")
log my u("3.1416")

यह थोड़ा अधिक गोल्फ हो सकता है, लेकिन शायद इसके लायक नहीं है।

आउटपुट:

(*5, 3*)
(*0, 1*)
(*1, 667*)
(*355, 113*)

2

ईसा पूर्व, 151 148 बाइट्स

संपादित करें - तेज और छोटा संस्करण

define f(v){s=scale(x=v);for(i=r=1;i<=10^s;i+=1){t=v*i+1/2;scale=0;p=t/=1;scale=s+1;t=t/i+10^-s/2;scale=s;t=t/1-v;if((t*=-1^(t<0))<r){r=t;n=p;d=i}}}

एक ही परीक्षण मामला।

बहुत कुछ पिछले संस्करण के समान है, लेकिन हम सभी संभव n / d संयोजनों की कोशिश करने के बजाय, हम कई गुणा m == v * d और हर के घ के पिछड़े अवतरण के अवशेषों पर पहाड़ी पर चढ़ते हैं। फिर से गणना की शुद्धता समान है।

यह यहाँ है:

define f(v)
{
    s= scale(x=v)
    for( i=r=1; i <= 10^s; i+=1 ){
        t= v * i +1/2
        scale=0
        m=t/=1 # this rounded multiple becomes nominator if
               # backward quotient is first closest to an integer
        scale=s+1
        t= t / i +10^-s/2 # divide multiple back by denominator, start rounding again...
        scale=s
        t= t/1 - v # ...rounding done. Signed residue of backward quotient
        if( (t*= -1^(t < 0)) < r ){
            r=t
            n=m
            d=i
        }
    }
}

इस संस्करण में वास्तव में एक मात्र लूप है और यह केवल $ \ Theta \ left (\ operatorname {fractional_decimals} (v) \ right) $ अंकगणितीय ऑपरेशन करता है।

मूल - धीमा संस्करण

यह फ़ंक्शन सबसे छोटे नामांकक n और भाजक d की गणना करता है, ताकि अंश n / d भिन्न से भिन्न (v) अंकों के बराबर हो, जो किसी दिए गए दशमलव मान v के बराबर है।

define f(v){s=scale(v);j=0;for(i=r=1;j<=v*10^s;){scale=s+1;t=j/i+10^-s/2;scale=s;t=t/1-v;if((t*=-1^(t<0))<r){r=t;n=j;d=i};if((i+=1)>10^s){i=1;j+=1}};v}

परीक्षण का मामला:

define o(){ print "Input ",x,"\tOutput ",n,"/",d,"\n" }
f(1.7); o()
> 0
> Input 1.7       Output 5/3
> 0
f(0.); o()
> 0
> Input 0 Output 0/1
> 0
f(0.001); o()
> 0
> Input .001      Output 1/667
> 0
f(3.1416); o()
> 0
> Input 3.1416    Output 355/113
> 0

और यहाँ यह अछूता है:

define f(v)
{
    s=scale(x=v) # save in global for later print
    j=0
    # do a full sequential hill-climb over the residues r of v and all possible
    # fractions n / d with fractional_decimals(v) == s precision.
    for( i=r=1; j <= v * 10^s; ){
        scale=s+1
        t= j / i +10^-s/2 # start rounding...
        scale=s
        t= t/1 - v # ...rounding done. New residue, but still signed
        if( (t*= -1^(t < 0)) < r ){ # absolute residue better?
            # climb hill
            r=t
            n=j
            d=i
        }
        if( (i+=1) > 10^s ){ # next inner step. End?
            # next outer step
            i=1
            j+=1
        }
    }
    v
}

मैं स्वीकार करता हूं, मैंने एक एकल बाहरी लूप के अंदर एक दूसरे आंतरिक लूप का अनुकरण करके थोड़ा धोखा दिया, लेकिन बिना किसी और लूप स्टेटमेंट का उपयोग किए। और यही कारण है कि यह वास्तव में $ \ Theta \ left (v \ operatorname {fractional_decimals} (v) ^ 2 \ right) $ अंकगणितीय ऑपरेशन करता है।


1
आपको संभवतः नए संस्करण को पोस्ट के सामने ले जाना चाहिए
गर्वित हेकलर

किया @proudhaskeller
Franki

1

सी, 233

यह एक परिक्षेपण फ़ंक्शन r () को शुरू करने वाले भाजक के साथ कॉल करके काम करता है। फ़ंक्शन एक अंश को बढ़ाना शुरू करता है, और प्रत्येक वृद्धि पर जाँच करता है कि क्या परिणामी संख्या, जब मूल के समान अंकों की संख्या में गोल हो, एक ही स्ट्रिंग है मूल के रूप में प्रतिनिधित्व। एक बार अंश को इतना बढ़ा दिया जाता है कि परिणाम मूल से अधिक हो जाता है, फ़ंक्शन हर को बढ़ाता है और खुद को कॉल करता है।

यह पाठ्यक्रम बहुत अधिक कोड का उपयोग करता है, लेकिन मुझे लगता है कि समस्या की भावना इस नंगे हड्डियों के दृष्टिकोण को बढ़ाती है; हम सभी जानते हैं कि, आधुनिक भाषाओं के आंतरिक परिमेय () कार्यों में बहुत सारी आंतरिक छोरें होती हैं।

ध्यान दें कि यह "0." इनपुट के लिए काम नहीं करता है क्योंकि यह फ्लोट लिखने के लिए एक मानक तरीका नहीं है, इसलिए जब यह फ्लोट को स्ट्रिंग में फिर से लिखता है, तो परिणाम कभी भी "0." नहीं होगा।

चश्मा एक ऐसा फ़ंक्शन चाहते हैं जो स्क्रीन पर केवल मुद्रण के बजाय मान लौटाता है, इसलिए तर्क-पासिंग।

कोड (अपुष्ट):

void r(char* x, int* a, int* b) {
    int i = -1;
    char z[32];
    double v =atof(x);
    while(1) {
        i++;
        double y = ((double)i)/((double)(*b));
        double w;
        sprintf(z, "%.*f", strlen(strchr(x,'.'))-1, y);
        if(strcmp(x, z)==0) {
            *a = i;
            return;
        }
        w = atof(z);
        if(w > v) {
            (*b)++;
            r(x, a, b);
            return;
        }
    }
}

उपयोग:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[]) {
    int num;
    int denom = 1; // start with a denominator of 1
    r(argv[1], &num, &denom);
    printf("%d/%d\n", num, denom);
    return 0;
}

गोल्फ कोड:

typedef double D;
void r(char*x,int*a,int*b){int i=-1;char z[32];D v=atof(x);while(1){i++;D y=((D)i)/((D)(*b));D w;sprintf(z,"%.*f",strlen(strchr(x,'.'))-1,y);if(!strcmp(x,z)){*a=i;return;}w=atof(z);if(w>v){(*b)++;r(x,a,b);return;}}}

वास्तव में, हास्केल पुस्तकालय कार्यान्वयन में ( hackage.haskell.org/package/base-4.7.0.1/docs/src/… ), की परिभाषा approxRationalमें सिर्फ एक पुनरावर्ती सहायक कार्य है, और इससे अधिक लूपिंग नहीं है।
गर्व हैकेलर

ठीक है, मैं गलत था, यह वास्तव में दो पुनरावर्ती सहायक कार्य करता है, लेकिन कल्पना से यह ठीक है
गौरवशाली हैकेलर

मैं यह कहने की कोशिश नहीं कर रहा था कि किसी के समाधान अमान्य थे, बस एक के बाद एक बिना युक्तिकरण के पोस्ट करना चाहता था :)
RT

बेशक, लेकिन यह तथ्य कि परिभाषा में कोई लूप नहीं है अच्छा है, और वास्तव में, आपने अपनी पोस्ट में लिखा है "हम सभी जानते हैं, आधुनिक भाषाओं के आंतरिक तर्कसंगत () कार्यों में बहुत सारी आंतरिक लूप हैं।" इसलिए मैंने इसकी जाँच की।
गौरवशाली हेकलर

वैसे भी, समाधान कैसे काम करता है?
गौरवशाली हैकेलर

1

शुद्ध बैश, 92 बाइट्स

इस उत्तर के लिए एक आंशिक स्पष्टीकरण के रूप में , यहाँ इसे मिटा दिया गया है:

f=${1#*.}
q=${1//.}
for((n=0,d=1;x-q;x=2*10**${#f}*n/d+1>>1,n+=x<q,d+=x>q));{ :;}
echo $n/$d

विशेष रूप से:

  • बैश में पूर्णांक केवल अंकगणित है। इसलिए हम उचित रूप से सब कुछ 2 * 10 ^ (अंशों की संख्या) तक बढ़ाते हैं।
  • बैश दौर नीचे पूर्णांक निकटतम करने के लिए; उपरोक्त अभिव्यक्ति में 2 है इसलिए हम इसके बजाय निकटतम पूर्णांक ( ऊपर या नीचे) पर गोल कर सकते हैं ) के ।
  • सिर्फ एक पाश
  • हम जाँचते हैं कि तर्कसंगत ओवरशूट करता है या दशमलव को रेखांकित करता है और तदनुसार भाजक या अंश को बढ़ाता है।

आउटपुट:

$ for n in 1.7 0. 0.001 3.1416; do echo "    n = $n:"; ./unround.sh $n; done
    n = 1.7:
5/3
    n = 0.:
0/1
    n = 0.001:
1/667
    n = 3.1416:
355/113
$ 

एक काफी सरल होना चाहिए intग -only पोर्ट
डिजिटल ट्रामा

1

जावास्क्रिप्ट (E6) 85

F=r=>(l=>{for(n=r,d=1;l&&r!=((n=r*d+1/2|0)/d).toFixed(l);d++);})(r.length-2)||[n|0,d]

Ungolfed

F=r=>{
  l = r.length-2; // decimal digits
  if (l==0) return [r|0, 1] // if no decimal return the same (conv to number) with denominator 1

  // loop for increasing denominator 
  for(d = 2; 
      r != ( // loop until find an equal result
      // given R=N/D ==> N=R*D
      (n=r*d+1/2|0) // find possible numerator, rounding (+0.5 and trunc)
      /d).toFixed(l); // calc result to given decimals
      d++);
  return [n,d]
}

फायरफॉक्स / फायरबग कंसोल में टेस्ट

;["1.7","0.","0.001","3.1416","9.9999"].forEach(v => console.log(v,F(v)))

उत्पादन

1.7 [5, 3]
0. [0, 1]
0.001 [1, 667]
3.1416 [355, 113]
9.9999 [66669, 6667]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.