둥근 분수


22

분수를 10 진수로 변환하고 해당 숫자를 저장하려면 특정 양의 메모리 만 사용하기 때문에 반올림해야하는 경우가 있습니다. 소수점 5 자리 만 저장할 수 있고 5/3는 1.6667이된다고 가정합니다. 소수점 이하 두 자리 만 저장할 수 있으면 1.7이됩니다 (현재는 항상 0과 9.99 사이에 있다고 가정).

1.7로 반올림을 시도하고 분수를 되 찾으려면 1.7이 반올림 된 숫자라는 것을 알기 때문에 어려울 수 있습니다. 물론 당신은 17/10을 시도 할 수 있지만 그것은 '우아한'5/3에 비해 '추악한'분수입니다.

따라서 목표는 이제 가장 작은 분모가 b 인 분수 a / b를 찾는 것입니다. 이로 인해 올바로 반올림되면 소수점이 반올림됩니다.

세부

입력에 0과 1 사이의 숫자 ( '포함')와 10 (제외) 사이의 숫자가 포함 된 문자열이 포함됩니다. 첫 번째 숫자 다음에. 하자 말은 n숫자의 수를 나타낸다. [numerator, denominator]분자는 음수가 아니고 분모가 양수인 경우 두 개의 정수의 목록 / 배열 또는 합리적인 데이터 유형 (자체를 만들거나 내장을 사용할 수 있음)이어야합니다 . 분수 분자 / 분모는 n숫자 ( n-1소수점 뒤의 숫자)로 올바르게 반올림 될 때 입력과 같아야합니다 .

제한 사항 : 하나의 루프 문 만 허용됩니다. 즉 , 전체 코드에서 하나의 단일 반복문 (예 for: while또는 goto등)뿐만 아니라 목록 / 배열의 모든 요소에 코드를 적용 map하거나 fold적용하는 기능적 루프 만 사용할 수 있지만 자유롭게 '남용'할 수 있습니다 또는 재귀 등을 사용하십시오.

함수를 작성해야합니다. 언어에 함수가 없거나 (있는 경우에도) 입력이 변수 (또는 stdin을 통해 입력)에 저장되어 있다고 가정하고 결과를 인쇄하거나 파일에 쓸 수 있습니다. 가장 적은 바이트 수가 이깁니다.

반올림

반올림은 '기존의'반올림 규칙을 따라야합니다. 즉, 마지막으로 잘릴 숫자가 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
그러나 기능적 언어에는 루프와 같은 것이 없습니다. haskell의 적 예제 repeat는 그 인수의 무한 목록을 만듭니다. 나는 루프하는 것처럼 보이지만 실제로는 O (1)의 시간 복잡성이 있습니다. 그러나 각 경우를 개별적으로 정렬하는 것이 기능적 언어를 허용하지 않는 것보다 낫습니다.
자랑스런 Haskeller

3
"loop"의 현재 정의가 마음에 들지 않습니다. 예를 들어 파이썬에서는 for n in numbers: f(g(n))과 같습니다 map(f, map(g, numbers)). 기능 버전은 map두 번 사용하는데 실제로 허용되지 않아야합니까?
flornquake

1
@ MartinBüttner 나는 함수형 언어 때문에 모호함으로 허용 될 수있는 경우에 대해 이야기
자랑 haskeller

1
함수형 프로그래밍에 대한 나의 지식은 기본적으로 제로이기 때문에 그 토론에 실제로 기여할 수 없어서 유감입니다. '규칙'을 준수하는지 확실하지 않은 솔루션이있는 경우 어쨌든 제출하십시오! 결국 그것은 재미 있고 교육적인 도전이되어야합니다!
flawr

2
@Dennis No 불행한 표현은 원하는 형식으로 제출할 수 있습니다.이 단락의 주요 아이디어는 입력 번호를 '읽기'위해 언어에 더 많은 바이트가 필요한 경우 단점이 없다는 것입니다.
flawr

답변:


4

CJam, 41 40 36 바이트

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

입력 문자열이 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

T-SQL 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
Tom Chantler

1
+1 나는 여기에 SQL 언어를 기대하지 않았습니다 !!!
flawr

@TomChantler 나는 당신이 결국 의미하는 것을 의심한다 :)
MickyT

@flawr 솔직히 말해서 나는 그것이 작동 할 것이라고 생각하지 않았다.
MickyT

12

하스켈, 62 59

이름 만 길지 않았다면 ...

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

이것은 Rational값을 반환하는 함수 입니다.

설명 : 이 함수 approxRational는 float 숫자와 float epsilon을 취하고 입력의 거리 epsilon에있는 가장 간단한 이성을 반환하는 함수입니다. 기본적으로 플로트의 가장 간단한 근사값을 "용서할 수있는 오류"거리에서 합리적으로 반환합니다.

우리가 사용하기 위해이 기능을 이용합시다. 이를 위해 우리는 주어진 수로 반올림되는 수레의 면적이 무엇인지 알아 내야합니다. 이것을 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"에서는 작동하지 않습니다. Haskell의 파서 함수는 .float의 끝에서를 인식하지 못하기 때문에 로 교체 read s하여 5 바이트 동안 고정 할 수 있습니다 read$s++"0".


흥미로운 기능입니다. 일반적으로 이러한 함수는 가장 적은 단계에서 숫자에 대한 가장 합리적인 근사치를 찾는 목적으로 존재하며, 이는 잘린 연속 분수 표현을 사용하여 달성 할 수 있습니다. 또는 분모가 가장 낮은 분수를 찾는 것이 학문적 호기심입니다. 일반적으로 표준 라이브러리 함수로 기대하지 않습니다.
COTO

4
@COTO 글쎄, 이것은 Haskell입니다, 그것은 학문적 연구로 가득합니다.
자랑스런 Haskeller

7

루비, 127125 바이트

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

매스 매 티카, 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
하하 나는 똑같은 해결책을 사용했다. 하스켈에서 너무 나빠요. btw, 솔루션에서 스펙에 필요한 문자열을 입력으로 사용하는 것처럼 보이지 않습니다.
자랑스런 Haskeller

잠깐, 입력은 문자열입니까? Dang, 그것은 코드에서 몇 가지 물건을 가져올 수 있음을 의미합니다.
Tally

분모를 최소화하기위한 제약 조건이 아니기 0.001때문에에 대한 출력 이 OP와 일치하지 않습니다 Rationalize. 내가 자랑스런 Haskeller에 대해 언급했듯이, 분모를 최소화하는 합리적인 근사 함수는 매우 난해합니다 (짧은 숫자로 근사하고 비효율적 인 방식이기 때문에). 나는 보통 그것이 표준 라이브러리 함수라고 기대하지 않습니다.
COTO

@COTO 워드 프로세서에 따르면 그것은 않습니다 하지만 분모를 최소화 할 수 있습니다.
Martin Ender

@ MartinBüttner : 출력되는 것이 흥미 롭습니다 1/999. 999는 대략 1e-6과 2e-6 사이의 오류에 대해서만 (허용 가능한) 최저 분모가됩니다. 오차 한계는 분명히 5e-4입니다. 따라서 Mathematica가이 경우에 무엇을 하든지 사양에 맞지 않습니다. : P
COTO

4

Python 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

APL, 50

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

긴로서 당신은 계산하지 않는 evaltoString루프로

설명

접근 방법은 분모로 1 ~ 10000 이상을 반복하고 부동 소수점과 가장 일치하는 분자를 계산 한 다음 오류가 범위 내에 있는지 확인하는 것입니다. 마지막으로, 발견 된 모든 분수에서 가장 작은 쌍을 선택하십시오.

(⍎x←⍞)화면에서 문자열 입력을 받고에 할당 x하고 eval
⍳1e51에서 10000 사이의 배열 생성 배열의
{...}¨각 요소에 대해 함수와 (⍎x←⍞)인수를 사용하여 함수를 호출하십시오 (루프)

⍺×⍵곱하기 인수
⌊.5+라운드 오프 (다음 아래로 반올림 0.5을 추가하여)
n←할당에 n
⍺-⍵÷⍨오른쪽 인자에 의해 분할 후 왼쪽 인자에서 빼기
(10*⍴x)×"의 길이의 힘에 10을 곱 x"
|절대 값 가져
50>미만 50 (길이가 있는지 확인을 x더 2입니다 dp 수보다 0.5이므로 대신 50을 사용하십시오.)
:n ⍵⋄''이전 검사에서 true를 반환하면 배열 n과 오른쪽 인수를 반환하고 그렇지 않으면 빈 문자열을 반환합니다.

⍎⍕ toString그런 다음 eval배열의 모든 숫자의 배열을 가져옵니다.
2↑발견 된 첫 번째 분자 분모 쌍 인 처음 두 요소 만 선택하십시오.


2

GNU dc, 72 바이트

루프 없음-dc에는 루프가 없습니다. 대신 제어는 단일 꼬리 재귀 매크로-dc에 대한 관용적입니다.

?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 =)
flawr을 발견

2

Applescript,> 300 바이트

기본적으로 필요한 반올림 유형을 수행하는 언어 로이 작업을 수행하고 싶었습니다. Applescript가 청구서에 맞는 것으로 나타났습니다. 그런 다음 enum을 보았고 rounding as taught in school골프 목적으로 Applescript의 뻔뻔스러운 경쟁에도 불구하고 사용을 거부 할 수 없었습니다.

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

BC, 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 조합을 시도하는 대신 v의 잔차와 배수 m = = v * d 및 분모 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) $ 산술 연산 만 수행합니다.

원본-느린 버전

이 함수는 fractional_decimals (v) 자릿수로 반올림 된 분수 n / d가 주어진 10 진수 값 v와 같도록 가장 작은 nominator n과 denominator d를 계산합니다.

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
새 버전을 포스트의 앞쪽으로 옮겨야합니다
자랑스런 Haskeller

@proudhaskeller 완료
Franki

1

C, 233

이 함수는 시작 분모가 1 인 합리화 함수 r ()을 호출하여 작동합니다.이 함수는 분자 증가를 시작하고 결과 숫자가 원래 숫자와 동일한 자릿수로 반올림 될 때 동일한 문자열을 갖는지 여부를 확인할 때마다 증가합니다. 원본으로 표현. 분자가 너무 커져서 결과가 원래보다 커지면 함수는 분모를 증가시키고 자체를 호출합니다.

물론 이것은 훨씬 더 많은 코드를 사용하지만 문제의 정신이이 기본 접근 방식을 능가한다고 생각합니다. 우리가 아는 한, 현대 언어의 내부 rationalize () 함수에는 많은 내부 루프가 있습니다.

"0"의 입력에는 작동하지 않습니다. float를 쓰는 표준 방법이 아니기 때문에 float를 문자열에 다시 쓸 때 결과는 "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;}}}

실제로 Haskell 라이브러리 구현 ( hackage.haskell.org/package/base-4.7.0.1/docs/src/… )에서 정의는 approxRational재귀 도우미 함수가 하나만 있으며 그 이상의 반복은 없습니다.
자랑스런 Haskeller

글쎄, 내가 틀렸다, 그것은 실제로 두 개의 재귀 도우미 기능을 가지고 있지만 사양에 따르면 괜찮습니다
자랑스런 haskeller

나는 누군가의 솔루션이 유효하지 않다고 말하려고하지 않고 내장 된 합리화없이 솔루션을 게시하고 싶었습니다.
RT

물론, 정의 자체에 루프가 없다는 사실은 훌륭합니다. 사실 여러분은 "우리가 아는 한, 현대 언어의 내부 rationalize () 함수에는 많은 내부 루프가 있습니다." 그래서 나는 그것을 확인했다.
자랑스런 Haskeller

어쨌든 솔루션은 어떻게 작동합니까?
자랑스런 Haskeller

1

순수한 배쉬, 92 바이트

이 답변에 대한 부분 설명으로 여기에 bash로 포팅됩니다.

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

특히 :

  • bash에는 정수 전용 산술이 있습니다. 따라서 우리는 모든 것을 2 * 10 ^ (소수 자릿수)만큼 적절하게 확장합니다.
  • bash 는 가장 가까운 정수 로 내림 합니다. 위 식에서 2는 가장 가까운 정수 ( 위 또는 아래) 로 반올림 할 수 있습니다. ) .
  • 하나의 루프
  • 우리는 합리적인 오버 슈트 또는 언더 슈트가 10 진수인지 확인하고 분모 또는 분자를 적절히 증가시킵니다.

산출:

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

intc에 대한 매우 간단한 전용 포트 여야 함
Digital Trauma

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]

언 골프

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

FireFox / FireBug 콘솔에서 테스트

;["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.