एन-डिजिट सटीक के साथ अनुमानित फ्लोटिंग पॉइंट नंबर


9

हमारे पास r0 और 1 के बीच एक फ्लोटिंग पॉइंट नंबर है , और एक पूर्णांक है p

सबसे छोटे भाजक के साथ पूर्णांक का अंश ज्ञात करें, जो rकम से कम- pसटीक परिशुद्धता के साथ सन्निकट है ।

  • इनपुट्स: r(एक फ्लोटिंग पॉइंट नंबर) और p(पूर्णांक)।
  • आउटपुट: aऔर bपूर्णांक, जहां
    • a/b(फ्लोट के रूप में) अंक rतक अनुमानित है p
    • b इस तरह के धनात्मक पूर्णांक संभव सबसे छोटा है।

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

  • यदि r=0.14159265358979और p=9,
  • तो परिणाम है , a=4687औरb=33102
  • क्योंकि 4687/33102=0.1415926530119026

किसी भी समाधान को सिद्धांत में मनमाने ढंग से सटीक प्रकारों के साथ काम करना पड़ता है, लेकिन कार्यान्वयन के निश्चित-सटीक प्रकारों के कारण सीमाएं मायने नहीं रखती हैं।

परिशुद्धता का अर्थ है " 0." के बाद अंकों की संख्या r। इस प्रकार, यदि r=0.0123और p=3, तब से a/bशुरू होना चाहिए 0.012। यदि pभिन्नात्मक भाग के पहले अंक r0 हैं, तो अपरिभाषित व्यवहार स्वीकार्य है।

जीत मानदंड:

  • एल्गोरिदम सबसे तेज एल्गोरिथ्म जीतता है। गति को O (p) में मापा जाता है।
  • यदि कई सबसे तेज़ एल्गोरिदम हैं, तो सबसे छोटी जीत है।
  • मेरे स्वयं के उत्तर को संभावित विजेताओं के सेट से बाहर रखा गया है।

पीएस गणित भाग वास्तव में बहुत आसान है जैसा कि ऐसा लगता है, मैं इस पोस्ट को पढ़ने का सुझाव देता हूं ।

जवाबों:


7

जावास्क्रिप्ट, ओ (10 पी ) और 72 बाइट्स

r=>p=>{for(a=0,b=1,t=10**p;(a/b*t|0)-(r*t|0);a/b<r?a++:b++);return[a,b]}

यह साबित करने के लिए तुच्छ है कि लूप अधिकांश ओ (10 पी ) पुनरावृत्तियों के बाद किया जाएगा ।

नील के विचार के लिए बहुत धन्यवाद, 50 बाइट बचाओ।


क्यों आप के साथ padEndऔर आसपास fiddling हैं match? क्या आप sliceप्रत्येक स्ट्रिंग को सही लंबाई तक नहीं कर सकते हैं और फिर उन्हें घटा सकते हैं?
नील

@Neil क्षमा करें, मैंने आपकी बात नहीं पकड़ी। जोड़ा padEndटेस्टकेस के लिए उपयोग किया जाता है f(0.001,2)और f(0.3,2)
tsh

मैं सोच रहा था कि आप (r,p)=>{for(a=0,b=1;`${a/b}`.slice(0,p+2)-`${r}`.slice(0,p+2);a/b<r?a++:b++);return[a,b]}(पूरी तरह से गोल्फ नहीं) की तर्ज पर कुछ आसान कर सकते हैं ।
नील

@ नील 120 -> 70 बाइट्स। :)
टीएसपी १17

वाह, यह बहुत बेहतर है!
नील

4

हास्केल , ओ (10 पी ) सबसे खराब स्थिति में 121 119 बाइट्स

g(0,1,1,1)
g(a,b,c,d)r p|z<-floor.(*10^p),u<-a+c,v<-b+d=last$g(last$(u,v,c,d):[(a,b,u,v)|r<u/v])r p:[(u,v)|z r==z(u/v)]

इसे ऑनलाइन आज़माएं!

2 बाइट्स लाईकोनी के लिए धन्यवाद

मैंने /math/2432123/how-to-find-the-fraction-of-integers-with-the-smallest-denominator-matching-an-i से एल्गोरिथ्म का उपयोग किया ।

प्रत्येक चरण में, नया अंतराल पिछले अंतराल का एक आधा होता है। इस प्रकार, अंतराल आकार है 2**-n, जहां nवर्तमान कदम है। जब 2**-n < 10**-p, हम सही अनुमान लगाते हैं। फिर भी अगर n > 4*pतो 2**-n < 2**-(4*p) == 16**-p < 10**-p। निष्कर्ष यह है कि एल्गोरिथ्म है O(p)

EDIT जैसा कि एक टिप्पणी में orlp द्वारा बताया गया है, ऊपर का दावा गलत है। सबसे खराब स्थिति में, r = 1/10**p( r= 1-1/10**pसमान है), 10**pचरण होंगे 1/2, 1/3, 1/4, ...:। एक बेहतर समाधान है, लेकिन मेरे पास इसे ठीक करने के लिए अभी समय नहीं है।


मुझे पता है कि कोड गोल्फ केवल माध्यमिक लक्ष्य है, लेकिन आप f=दो बाइट्स को छोड़ सकते हैं और बचा सकते हैं z<-floor.(*10^p),u<-a+c,v<-b+d
लकोनी

@ लिकोनी मैंने दो बाइट्स नहीं गिना। मुझे नहीं पता कि f=हास्केल कोड में टीआईओ को कैसे निकालना है ।
जफरार्ड

आप -cppसंकलक ध्वज जोड़ सकते हैं और f=\ शीर्ष लेख में लिख सकते हैं : इसे ऑनलाइन आज़माएं!
लकोनी

"प्रत्येक चरण में, नया अंतराल पिछले अंतराल का एक आधा है।" तुम यह कैसे जानते हो? पहला चरण 1/2 है, हां, लेकिन फिर अगला चरण उदाहरण के लिए है 1/2 और 1/1 का औसत 2/3, जो अंतराल को रोक नहीं रहा है।
orlp

@orlp आप पूर्ण रूप से सही हैं। मैं अभी भी बहुत आशावादी था और सबसे खराब स्थिति में जटिलता O (10 ^ p) है। मेरे पास एक बेहतर समाधान है लेकिन अभी इसे लिखने का समय नहीं है।
जेफर्ड

0

सी, 473 बाइट्स (बिना संदर्भ के), ओ (पी), गैर-प्रतिस्पर्धात्मक

यह समाधान इस उत्कृष्ट पोस्ट में विस्तृत गणित भाग का उपयोग करता है । मैंने केवल calc()उत्तर आकार में गणना की ।

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

void calc(float r, int p, int *A, int *B) {
  int a=0, b=1, c=1, d=1, e, f;
  int tmp = r*pow(10, p);
  float ivl = (float)(tmp) / pow(10, p);
  float ivh = (float)(tmp + 1) / pow(10, p);

  for (;;) {
    e = a + c;
    f = b + d;

    if ((ivl <= (float)e/f) && ((float)e/f <= ivh)) {
      *A = e;
      *B = f;
      return;
    }

    if ((float)e/f < ivl) {
      a = e;
      b = f;
      continue;
    } else {
      c = e;
      d = f;
      continue;
    }
  }
}

int main(int argc, char **argv) {
  float r = atof(argv[1]);
  int p = atoi(argv[2]), a, b;
  calc(r, p, &a, &b);
  printf ("a=%i b=%i\n", a, b);
  return 0;
}

यह कम से कम पारंपरिक मशीनों पर, सीपीयू चक्रों के अर्थ में संभवतः सबसे तेज़ संभव समाधान भी पास करता है।
पीटर - मोनिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.