끈을 둥글게


10

일부 십진수는 이진 부동 소수점의 내부 표현으로 인해 이진 부동 소수점으로 정확하게 표현 될 수 없습니다. 예를 들어 14.225를 소수점 이하 두 자리로 반올림하면 14.23이 아니라 14.22가됩니다.

파이썬 :

In: round(14.225, 2)
Out: 14.22

그러나 '14 .225 '로 14.225의 문자열 표현이 있다고 가정하면 원하는 반올림 '14 .23'을 문자열 표현으로 얻을 수 있어야합니다.

이 방법은 임의의 정밀도로 일반화 할 수 있습니다.

가능한 파이썬 2/3 솔루션

import sys

def round_string(string, precision):
    assert(int(precision) >= 0)
    float(string)

    decimal_point = string.find('.')
    if decimal_point == -1:
        if precision == 0:
            return string
        return string + '.' + '0' * precision

    all_decimals = string[decimal_point+1:]
    nb_missing_decimals = precision - len(all_decimals)
    if nb_missing_decimals >= 0:
        if precision == 0:
            return string[:decimal_point]
        return string + '0' * nb_missing_decimals

    if int(all_decimals[precision]) < 5:
        if precision == 0:
            return string[:decimal_point]
        return string[:decimal_point+precision+1]

    sign = '-' if string[0] == '-' else '' 
    integer_part = abs(int(string[:decimal_point]))
    if precision == 0:
        return sign + str(integer_part + 1)
    decimals = str(int(all_decimals[:precision]) + 1)
    nb_missing_decimals = precision - len(decimals)
    if nb_missing_decimals >= 0:
        return sign + str(integer_part) + '.' + '0' * nb_missing_decimals + decimals
    return sign + str(integer_part + 1) + '.' + '0' * precision

온라인으로 사용해보십시오!

사용법 :

     # No IEEE 754 format rounding
In:  round_string('14.225',2)
Out: '14.23'

     # Trailing zeros
In:  round_string('123.4',5)
Out: '123.40000'

In: round_string('99.9',0)
Out: '100'

    # Negative values
In: round_string('-99.9',0)
Out: '-100'

In: round_string('1',0)
Out: '1'

    # No unnecessary decimal point
In: round_string('1.',0)
Out: '1'

    # No unnecessary decimal point
In: round_string('1.0',0)
Out: '1'

In:  for i in range(8): 
         print(round_string('123456789.987654321',i))
Out: 123456790
     123456790.0
     123456789.99
     123456789.988
     123456789.9877
     123456789.98765
     123456789.987654
     123456789.9876543

직무

입력 인수 1 : 포함하는 문자열

  • 하나 이상의 자리 ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  • 소수점 이하 자릿수 ( .)는 하나 이상이어야하며
  • -첫 문자 인 선택적인 빼기 ( ).

입력 인수 2 : 음이 아닌 정수

출력 : 올바르게 반올림 된 (기본 10) 문자열

반올림 = 반에서 0으로 반올림

이것은 입니다. 가장 적은 바이트 수가 이깁니다!


@KevinCruijssen 1) 구현 본문에서 문자열을 고수 할 필요가 없으며 내장 반올림을 사용할 수 있습니다. 불행하게도 (물론) IEEE 754 표준은 널리 사용되는 표준이므로 내장 반올림으로 원하는 동작이 발생하지 않습니다. 2) 좋아, 샌드 박스를 알지 못했다.
Matthias

TI 기본 : round(A,B5 바이트
Julian Lachniet

1
두 번째 입력 인수와 관련하여 : 0양의 정수가 아니라 "음이 아닌"입니다.
Stewie Griffin

1
필요한 경우 후행 0을 추가한다고 가정합니까? 에 대한 테스트 사례를 추가 할 수 123.4 & 5 --> 123.40000있습니까? 아니면 두 번째 입력이 첫 번째 입력의 포인트 이후의 소수점 이하 자릿수보다 크지 않다고 가정 할 수 있습니까?
Kevin Cruijssen

1
@ Matthias Python과 JavaScript를 통합 할 수 없다면 (파이썬과 JS를 거의 프로그래밍하지 않았으므로 가능하면 솔직히 모르겠습니다) 아니오. 하지만 언제든지 테스트 코드와 함께 온라인으로 사용해보십시오 . 링크를 추가 할 수 있습니다. 편집 : 또한 일반적으로 답변을 수락 할 때까지 며칠 이상 기다리는 것이 좋습니다.
케빈 크루이 센

답변:



5

펄, 22 20 바이트

printf"%.*f",pop,pop

사용 :

perl -e 'printf"%.*f",pop,pop' 123456789.987654321 3

Dada의 코드 버전입니다. 이전:

printf"%*2\$.*f",@ARGV

2
printf"%.*f",pop,pop작동해야 함
Dada

5

PHP, 33 31 바이트

PHP도 올바르게 반올림합니다 (적어도 64 비트).

printf("%.$argv[2]f",$argv[1]);

명령 행 인수에서 입력을받습니다. 로 실행하십시오 -r.

PHP, 내장되지 않음, 133 바이트

[,$n,$r]=$argv;if($p=strpos(_.$n,46))for($d=$n[$p+=$r],$n=substr($n,0,$p-!$r);$d>4;$n[$p]=(5+$d=$n[$p]-4)%10)$p-=$n[--$p]<"/";echo$n;

온라인으로 실행 -nr하거나 테스트하십시오 .

고장

[,$n,$r]=$argv;             // import arguments
if($p=strpos(_.$n,46))      // if number contains dot
    for($d=$n[$p+=$r],          // 1. $d= ($r+1)-th decimal 
        $n=substr($n,0,$p-!$r); // 2. cut everything behind $r-th decimal
        $d>4;                   // 3. loop while previous decimal needs increment
        $n[$p]=(5+$d=$n[$p]-4)%10   // B. $d=current digit-4, increment current digit
    )
        $p-=$n[--$p]<"/";           // A. move cursor left, skip dot
echo$n;

널 바이트가 작동하지 않습니다. 그래서 사용해야 substr합니다.


1
"%.$argv[2]f"대신 "%.{$argv[2]}f"2 바이트를 절약하여 쓸 수 있습니다 .
Ismael Miguel

4

루비 2.3, 12 + 45 = 57

BigDecimal내장 기능을 사용 하지만 사용하기 전에 필요하므로 플래그로 사용하는 것이 더 저렴합니다.

깃발: -rbigdecimal

함수:

->(s,i){BigDecimal.new(s).round(i).to_s('f')}

루비 2.3은 기본적으로 ROUND_HALF_UP


4

자바 스크립트 (ES6), 44 바이트

n=>p=>(Math.round(n*10**p)/10**p).toFixed(p)

온라인으로 사용해보십시오 :

const f = n=>p=>(Math.round(n*10**p)/10**p).toFixed(p)

console.log(f('14.225')(2));

[...Array(8).keys()].map(i=>console.log(f('123456789.987654321')(i)))

console.log(f('123.4')(5))


4

파이썬 114 105 103 96 91 89 바이트

Kevin Cruijssen 덕분에 5 바이트 절약 Krazor
덕분에 2 바이트 절약

from decimal import*
d=Decimal
lambda x,y:d(x).quantize(d('0.'[y>0]+'1'*y),ROUND_HALF_UP)

온라인으로 사용해보십시오!


1
from decimal import *그리고 3을 제거하는 d.것은 4 바이트 더 짧다.
Kevin Cruijssen

@ KevinCruijssen : 감사합니다!
Emigna

2
당신은 또한 할 수 d=Decimal있고 d() , 또 다른 5를 구할 수 있습니다. (잘못, 매우 졸려요)
FMaz

@ Krazor : 내가 잘못하지 않으면 2 바이트를 절약했습니다. 감사!
Emigna

웁스, 그게 내가 의미 한 바야. 어쨌든 내 졸린 생각을 떠날 것입니다.
FMaz


3

BASH, 26 23 21 바이트

bc<<<"scale=$2;$1/1"

용법

round_string.sh에 저장, chmod + x round_string.sh

./round_string.sh 23456789.987654321 3

편집 : 라이브러리를로드 할 필요가 없습니다


설명 : bc는 임의의 정밀도를 사용하고, 스케일 값을 두 번째 매개 변수로 포함하는 '<<<'와 여기에 doc을 작성하고 첫 번째 매개 변수를 1로 나누어 스케일 해석을 강제 실행하십시오.
marcosm

2
이것은 제공 14.22입력을 위해 14.225 2, 그리고14.23
디지털 외상에게

3

AHK, 25 바이트

a=%1%
Send % Round(a,%2%)

변수 이름이나 숫자를 받아들이는 함수에서 AHK가 전달 된 매개 변수를 직접 사용할 수 없다는 사실에 다시 한 번 강조합니다. 내가 교체하는 경우 a1Round기능, 그것은 값을 사용합니다 1. 내가하려고하면 %1%, 그것은 첫 번째 인수의 사용하려고 내용을 일을하지 않는 변수 이름으로. 다른 변수로 설정 해야하는 데 6 바이트가 소요되었습니다.


3

배치, 390 바이트

@echo off
set s=%1
set m=
if %s:~,1%==- set m=-&set s=%s:~1%
set d=%s:*.=%
if %d%==%s% (set d=)else call set s=%%s:.%d%=%%
for /l %%i in (0,1,%2)do call set d=%%d%%0
call set/ac=%%d:~%2,1%%/5
call set d=00%s%%%d:~,%2%%
set z=
:l
set/ac+=%d:~-1%
set d=%d:~,-1%
if %c%==10 set c=1&set z=%z%0&goto l
set d=%m%%d:~2%%c%%z%
if %2==0 (echo %d%)else call echo %%d:~,-%2%%.%%d:~-%2%%

설명. 해당되는 경우 부호를 추출하여 시작합니다. 그런 다음 숫자를 정수와 분수로 나눕니다. 분수는 숫자 n+1보다 큰 n숫자 를 갖도록 0으로 채워집니다 . n번째 (제로 인덱스)는 숫자 5에 의해 분할하고,이 초기 캐리이다. 정수와 n분수가 연결되고 캐리는 문자별로 추가됩니다. 캐리지 리플이 멈춘 후 숫자가 재구성되고 소수점이 삽입됩니다.


3

TI 기본, 53 16 바이트

TI-Basic은 IEEE를 사용하지 않으며 아래 방법은 0-9 (포함) 10 진수 위치에서 작동합니다.

Prompt Str1,N
toString(round(expr(Str1),N

CE calcs의 성능을 보여준 @JulianLachniet에게 감사합니다 toString( 내가 알지 못하는 명령이 (Color Edition calcs OS 5.2 이상이 필요합니다).

추신 : 나는 두 번째 줄을 가지고 sub(Str1,1,N+inString(Str1,".있었지만 쓸모가 없다는 것을 깨달았습니다.


어떻게 N사용 되나요?
Matthias

@Matthias 그 오타를 잡아 주셔서 감사합니다! 실수로 이전 편집에서 마지막 3 바이트를 제거했습니다
Timtech

3

자바 7, 77 72 71 바이트

<T>T c(T n,int d){return(T)"".format("%."+d+"f",new Double(n+""));}

덕분에 -1 바이트 @cliffroot

72 바이트 답변 :

String c(String n,int d){return n.format("%."+d+"f",new Double(n));}

Python과 달리 Java는 이미 올바르게 반올림하고 사용할 때 이미 문자열을 반환합니다. String.format("%.2f", aDouble) 와 함께 2당신이 원하는 소수의 양으로 대체.

편집 / 참고 : 예, new Float(n)1 바이트보다 짧다는 것을 알고 new Double(n)있지만 테스트 사례에서는 실패합니다 123456789.987654321.Double vs Float에 관한이 테스트 코드를 참조하십시오.

설명:

<T> T c(T n, int d){               // Method with generic-T & integer parameters and generic-T return-type (generic-T will be String in this case)
  return (T)"".format("%."+d+"f",  //  Return the correctly rounded output as String
    new Double(n+""));             //  After we've converted the input String to a decimal
}                                  // End of method

테스트 코드 :

여기에서 시도하십시오.

class M{
  static <T>T c(T n,int d){return(T)"".format("%."+d+"f",new Double(n+""));}

  public static void main(String[] a){
    System.out.println(c("14.225", 2));
    System.out.println(c("123.4", 5));
    System.out.println(c("99.9", 0));
    System.out.println(c("-99.9", 0));
    System.out.println(c("1", 0));
    System.out.println(c("1.", 0));
    System.out.println(c("1.0", 0));
    for(int i = 0; i < 8; i++){
      System.out.println(c("123456789.987654321", i));
    }
  }
}

산출:

14.23
123.40000
100
-100
1
1
1
123456790
123456790.0
123456789.99
123456789.988
123456789.9877
123456789.98765
123456789.987654
123456789.9876543

1
1 바이트 더 짧음 :<T>T c(T n,int d){return(T)"".format("%."+d+"f",new Double(n+""));}
cliffroot

2
이 솔루션 은 작동하지 않습니다 . 예제는 반올림 / 짝수 0 반올림 문제 일 수 있지만 부동 소수점 오류가 발생하고 OP는 임의의 정밀도를 지원해야한다고 명확히했습니다.
CAD97

1
: 사실, 당신은 당신이 여기에서 재생되는 문제의 예를 사례를 실패 123456789.987654321, 4해야 123456789.9877하지123456789.9876
CAD97

2

파이썬 (2/3), 394 바이트

def rnd(s,p):
    m=s[0]=='-'and'-'or''
    if m:s=s[1:]
    d=s.find('.')
    l=len(s)
    if d<0:
        if p>0:d=l;l+=1;s+='.'
        else:return m+s
    e=(d+p+1)-l
    if e>0:return m+s+'0'*e
    o=''
    c=0
    for i in range(l-1,-1,-1):
        x=s[i]
        if i<=d+p:
            if i!=d:
                n=int(x)+c
                if n>9:n=0;c=1 
                else:c=0
                o+=str(n)
            else:
                if p>0:o+=x
        if i==d+p+1:c=int(x)>4
    if c:o+='1'
    return m+''.join(reversed(o))

임의의 정밀도 숫자에 사용됩니다.


5
PPCG에 오신 것을 환영합니다! 그러나 이것은 골프가 아닙니다. 있다 많이 제거 할 수 공백의는. 이 사이트에 대한 답변은 골퍼가되어야합니다. 죄송합니다.
Rɪᴋᴇʀ

그냥 몇 가지 (아마 더 많을 수도 있습니다) ... 함수 이름은 1 바이트 일 수 있습니다. 첫 번째 줄은 s[0]<'0'문자열 곱셈을 사용할 수 있으며 사용할 수도 있습니다 m='-'*(s[0]<'0'). 블록 명령문 범위가없는 행은 ;(예 :)와 함께 결합 될 수 있습니다 o='';c=0. if줄 바꿈과 탭의 필요성을 더욱 줄이기 위해 일부 문을 목록 색인으로 대체 할 수 있습니다. 마지막 줄은 슬라이스 o[::-1]대신을 사용할 수 reversed(o)있으며 ''.join가 중복됩니다. 여러 return문장 이 필요하지 않도록 다시 작성할 수도 있습니다 .
Jonathan Allan


2

자바 스크립트 (ES6), 155 바이트

(s,n)=>s.replace(/(-?\d+).?(.*)/,(m,i,d)=>i+'.'+(d+'0'.repeat(++n)).slice(0,n)).replace(/([0-8]?)([.9]*?)\.?(.)$/,(m,n,c,r)=>r>4?-~n+c.replace(/9/g,0):n+c)

설명 : 문자열이 처음으로 포함하도록 정규화 .n+1소수점 자리. 그런 다음 후행 숫자, 선행 9s 또는 .s 및 모든 선행 숫자가 고려됩니다. 마지막 숫자가 5보다 작은 경우 숫자와 바로 앞의 숫자는 .단순히 제거되지만 5보다 큰 경우 9s가 s로 변경되고 0이전 숫자가 증가합니다 (또는 이전 숫자가 없으면 1이 앞에옵니다).



1

스칼라, 44 바이트

(s:String,p:Int)=>s"%.${p}f"format s.toFloat

테스트:

scala> var x = (s:String,p:Int)=>s"%.${p}f"format s.toFloat
x: (String, Int) => String = <function2>

scala> x("14.225",2)
res13: String = 14.23

1

Wonder , 10 바이트

@@fix#1E#0

용법:

@@fix#1E#0

필요한 경우 십진 정밀도를 설정하고 후행 0을 추가하십시오.


이것에 대한 TIO가 있습니까?
Matthias

없어요,하지만 설치가 매우 쉽습니다. Node.js (v6 +) 및가 있는지 확인하십시오 npm i -g wonderlang. wonder명령을 사용하여 REPL을 실행하고 코드를 붙여 넣습니다.
Mama Fun Roll

1

J, 22 17 바이트

((10 j.[)]@:":".)

NB.    2    ((10 j.[)]@:":".)   '12.45678'
NB.    12.46 

규칙에 대한 이해를 수정 한 @Conor O'Brien에게 감사합니다.

t=:4 :'(10 j.x)":".y'

    NB.    Examples
    NB.    4 t'12.45678'
    NB.    12.4568
    NB.    4 t'12.456780'
    NB.    12.4568
    NB.    4 t'12.4567801'
    NB.    12.4568
    NB.    2 t'12.45678'
    NB.      12.46
    NB.    2 t'12.4567801'
    NB.      12.46
    NB.    2 (10 j.[)":". '_12.4567801'
    NB.     _12.46

format    
    x t y
where x is a digit number of decimal places required and y
is the character string containing the value to be rounded.

이 문제를 해결하려면 소수점 이하 자릿수를 사용하여 N 정밀도 정밀도가 아닌 N 소수점으로 반올림해야합니다. 이에 따라 2 t '1234.456'주어야한다 1234.46대신6 t '1234.456'
코너 오브라이언
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.