আন-রাউন্ড ভগ্নাংশ


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 বা তার বেশি হয়, আপনি গোল হয়ে যাবেন এবং আপনি অন্য কোনও ক্ষেত্রে গোল করবেন, যেমন:

রাউন্ড করার সময় 4.5494 ফলাফল আসবে

  • 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
তবে কার্যকরী ভাষায় লুপের মতো জিনিস নেই। হাস্কেলের শত্রু উদাহরণ repeatতার যুক্তির অসীম তালিকা তৈরি করে। আমি লুপ মনে করি না তবে এটিতে ও (1) এর সময় জটিলতা রয়েছে। তবে আমি অনুমান করি যে প্রতিটি ক্ষেত্রে পৃথকভাবে বাছাই করা কার্যকরী ভাষা না দেওয়ার চেয়ে ভাল।
গর্বিত হাসেলেলার

3
আমি "লুপ" এর বর্তমান সংজ্ঞাটি পছন্দ করি না। পাইথনে, উদাহরণস্বরূপ, for n in numbers: f(g(n))সমান map(f, map(g, numbers))। ক্রিয়ামূলক সংস্করণটি mapদু'বার ব্যবহার করে, এটি কি সত্যই বাতিল করা উচিত?
ফ্লর্নকোয়াক

1
@ মার্টিনবাটনার আমি এই মামলার বিষয়ে কথা বলেছিলাম যে অস্পষ্টতার কারণে ক্রিয়ামূলক ভাষাগুলি নিষিদ্ধ করা হবে
গর্বিত হাসেলেলার

1
আমি দুঃখিত যে আমি কার্যত সেই আলোচনায় অংশ নিতে পারি না কারণ কার্যকরী প্রোগ্রামিং সম্পর্কে আমার জ্ঞানটি মূলত শূন্য। যদি আপনার এমন কোনও সমাধান থাকে যার বিষয়ে আপনি অনিশ্চিত হন যে এটি 'বিধি' মেনে চলে কিনা তা দয়া করে তা জমা দিন! শেষ পর্যন্ত এটি একটি মজাদার এবং শিক্ষামূলক চ্যালেঞ্জ হওয়ার কথা!
flawr

2
@ ডেনিস না এটি দুর্ভাগ্যজনক কথা ছিল, আপনি নিজের পছন্দ মতো যে কোনও আকারে এটি জমা দিতে পারেন, সেই অনুচ্ছেদের পিছনে মূল ধারণাটি ছিল যে আপনার ভাষা যদি ইনপুট নম্বরটি 'পড়ার' জন্য আরও বাইট নেয় তবে আপনার কোনও অসুবিধা হবে না।
flawr

উত্তর:


4

সিজেম, 41 40 36 বাইট

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

অনুমান করা হয় যে ইনপুট স্ট্রিং Q এ সঞ্চিত আছে, যা প্রশ্ন দ্বারা স্পষ্টভাবে অনুমোদিত allowed এটি অনলাইনে চেষ্টা করুন।

পরীক্ষার মামলা

$ 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

যদিও টি-এসকিউএল সত্যিই এই ধরণের জিনিসটির পক্ষে উপযুক্ত নয় তবে এটি চেষ্টা করা মজাদার। পারফরম্যান্স হ'ল ডিনামিনেটরের উচ্চতর খারাপ হয়। এটি 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.14159and 355/113
ুকিয়ে

1
+1 আমি এখানে কোনও এসকিউএল ভাষা দেখার আশা করিনি !!!
flawr

@ টমচ্যান্টলার আমার সন্দেহ হচ্ছে আপনি শেষ পর্যন্ত বলতে চাইছেন :)
মিকিটি

@ ফ্লোয়ার সত্য কথা বলতে গেলে আমি ভাবিনি যে এটি কাজ করে চলেছে .. যদিও খুব নিষ্ঠুর শক্তি পদ্ধতি।
মিকিটি

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.
উভয় সীমাই হ'ল ইনপুট নম্বর +/- 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." তে কাজ করে না কারণ হাস্কেলের পার্সার ফাংশনটি .একটি ভাসমানের শেষে সনাক্ত করে না । এটি প্রতিস্থাপন read sকরে 5 বাইটের জন্য স্থির করা যেতে পারে 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যা ফলাফল হিসাবে a প্রদান করে 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

গণিত, 49 53 টি অক্ষর

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
হাহা আমি ঠিক একই সমাধান ব্যবহার। হাস্কেল খুব খারাপ এটি দীর্ঘ। বিটিডব্লিউ, দেখে মনে হচ্ছে আপনার সমাধানটি কোনও ইনপুট হিসাবে স্ট্রিং নেয় যেমন অনুমানের দ্বারা প্রয়োজনীয়।
গর্বিত হাসেলেলার

অপেক্ষা করুন, ইনপুটটি কি একটি স্ট্রিং ছিল? ডাং, এর অর্থ আমি কোড থেকে কিছু স্টাফ টানতে পারি।
টালি

এর জন্য আপনার আউটপুট 0.001অপটির সাথে মেলে না কারণ হরককে 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

এপিএল, 50

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

যতক্ষণ আপনি গণনা করেন না evalএবং toStringলুপ হিসাবেও না

ব্যাখ্যা

পন্থাটি হ'ল 1 থেকে 10000 এর উপরে ডিনমিনেটর হিসাবে পুনরাবৃত্তি করা এবং অঙ্কটি গণনা করা যা ভাসমানটির সাথে সর্বাধিক সান্নিধ্যের সাথে মিলিত হয়, তারপরে ত্রুটিটি সীমার মধ্যে রয়েছে কিনা তা পরীক্ষা করে দেখুন। শেষ অবধি, পাওয়া সমস্ত ভগ্নাংশ থেকে ক্ষুদ্রতম জুটিটি নির্বাচন করুন।

(⍎x←⍞)স্ক্রিন থেকে স্ট্রিং ইনপুট নিন, বরাদ্দ করুন xএবং
⍳1e5অ্যারে থেকে 1 থেকে 10000 পর্যন্ত জেনারেট তৈরি করুন অ্যারের
{...}¨প্রতিটি উপাদানের জন্য, এটি (⍎x←⍞)এবং আর্গুমেন্ট (লুপ) দিয়ে কল করুন

⍺×⍵গুন আর্গুমেন্ট
⌊.5+রাউন্ড বন্ধ (0.5 যোগ তারপর rounding দ্বারা)
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}

এখানে কেউ পাই আনুমানিকতা দিবস উদযাপন করেন ?


না, আমি শুধুমাত্র টাও পড়তা দিন উদযাপন করছি = পি কিন্তু আমি শুধু লক্ষ্য করেছি যে, |। 355/113 - Pi | <10 ^ -6 =)
flawr

2

অ্যাপলস্ক্রিপ্ট,> 300 বাইট

আমি এমন ভাষায় এটি করতে চেয়েছিলাম যা স্থানীয়ভাবে গোলাকার ধরণের প্রয়োজন। অ্যাপলস্ক্রিপ্টটি বিলটি ফিট করে। তারপরে আমি এনাম দেখেছি 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}}}

একই পরীক্ষার কেস।

অনেকগুলি পূর্ববর্তী সংস্করণের সাথে সমান, তবে সমস্ত সম্ভাব্য এন / ডি সংমিশ্রণের চেষ্টা করার পরিবর্তে, আমরা ভি = র এবং অবশিষ্ট গুণফলের এম == ভি * ডি এবং ডিনোমিনিটার ডি'র অবশিষ্টাংশের উপরে পাহাড় বেয়ে উঠি। আবার গণনার যথার্থতা একই।

এখানে এটি অপরিবর্তিত:

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
        }
    }
}

এই সংস্করণটির সত্যই একটি মাত্র লুপ রয়েছে এবং এটি কেবল \ \ থেটা \ বাম (\ অপেরাটর্নাম {ভগ্নাংশ_সংশ্লিষ্ট} (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
}

আমি স্বীকার করি, আমি একক বাইরের লুপের ভিতরে দ্বিতীয় অভ্যন্তরীণ লুপটি অনুকরণ করে কিছুটা প্রতারণা করেছি, তবে আরও কোনও লুপ বিবৃতি ব্যবহার না করেই। এবং সে কারণেই এটি আসলে গাণিতিক ক্রিয়াকলাপগুলি v \ থেটা \ বামে (ভি \ অপার্যাটর্নাম {ভগ্নাংশ_পরিচয়} (ভি) ^ 2 \ ডান) $ পাটিগণিত ক্রিয়াকলাপগুলি করে।


1
আপনার সম্ভবত নতুন সংস্করণটি পোস্টের সামনের দিকে
নিয়ে যাওয়া উচিত

কাজ @proudhaskeller
Franki

1

সি, 233

এটি 1 এর প্রারম্ভিক ডিনোমিনেটরের সাথে যুক্তিযুক্তকরণ ফাংশন r () কল করে কাজ করে ফাংশনটি একটি অঙ্ককে বাড়িয়ে তোলা শুরু করে এবং ফলাফলের সংখ্যাটি যখন মূল হিসাবে একই সংখ্যায় গোল হয়, তখন একই স্ট্রিং রয়েছে কিনা তা প্রতিটি বৃদ্ধি পরীক্ষা করে দেখায় মূল হিসাবে উপস্থাপনা। একবার অঙ্কটি এত বাড়ানো হয়েছে যে ফলাফলটি আসলটির চেয়ে বড় হয়, ফাংশনটি ডিনোমিনেটরকে বাড়িয়ে তোলে এবং নিজেকে কল করে।

এটি অবশ্যই আরও অনেক কোড ব্যবহার করে তবে আমি মনে করি যে সমস্যার উদ্বেগটি এই নগ্ন-হাড়ের পদ্ধতির বহিঃপ্রকাশ ঘটায়; আমরা জানি, আধুনিক ভাষার অভ্যন্তরীণ যুক্তিযুক্তকরণ () ফাংশনগুলিতে প্রচুর অভ্যন্তরীণ লুপ রয়েছে।

মনে রাখবেন যে এটি "০" এর ইনপুটটির জন্য কাজ করে না কারণ এটি কোনও ফ্লোট লেখার মানক উপায় নয়, সুতরাং যখন এটি ফ্লোটটিকে স্ট্রিংতে পুনরায় লিখবে, ফলাফল কখনই "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কেবল একটি পুনরাবৃত্ত সহায়ক সহায়ক রয়েছে এবং এর চেয়ে লুপিং আর নেই।
গর্বিত হাসেলেলার

ঠিক আছে, আমি ভুল ছিলাম, এটিতে আসলে দুটি পুনরাবৃত্তকারী সহায়ক ফাংশন রয়েছে তবে
অনুমানের

আমি বলার চেষ্টা করছিলাম না যে কারওর সমাধানগুলি অবৈধ ছিল, কেবল বিল্ট-ইন যৌক্তিকরণ ছাড়াই একটি পোস্ট করতে চেয়েছিল :)
আরটি

অবশ্যই, কিন্তু সংজ্ঞাটি নিজেই কোনও লুপ নেই এই বিষয়টি আপনি খুব সুন্দর এবং সত্যই বলেছেন, আপনি আপনার পোস্টে লিখেছিলেন "আমরা জানি সবার জন্য, আধুনিক ভাষার অভ্যন্তরীণ যুক্তিযুক্তকরণ () ফাংশনগুলিতে প্রচুর অভ্যন্তরীণ লুপ থাকে।" তাই আমি এটি পরীক্ষা করেছিলাম।
গর্বিত হাসেলেলার

যাইহোক, সমাধান কিভাবে কাজ করে?
গর্বিত হাসেলেলার 21

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

লক্ষণীয়ভাবে:

  • বাশের পূর্ণসংখ্যার গণিত রয়েছে has সুতরাং আমরা যথাযথভাবে 2 * 10 everything (ভগ্নাংশের সংখ্যার) দ্বারা স্কেল করি।
  • ব্যাশ চক্রের নিচে পূর্ণসংখ্যা নিকটতম করা; উপরের মত প্রকাশের 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সি থেকে মোটামুটি সোজা- একমাত্র বন্দর হওয়া উচিত
ডিজিটাল ট্রমা

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]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.