2017-12-16 18 views
0

나는 여러 시간 동안 검색을 해왔으며 다음과 같은 간단한 방법을 찾을 수 없다.파이썬 증분 부동 소수점으로 가능한 한 가장 작은 단계로 소수점 이하 자릿수로 미리 결정됨

Value 1 = 0.00531 
Value 2 = 0.051959 
Value 3 = 0.0067123 

나는 가장 작은 소수점 (가 시작하고 소수의 수, 각 값에 따라서 내 문제가 다양하지만, 수는 소수점의 정확한 수를 유지해야합니다)에 의해 각각의 값을 증가하고자합니다.

Value 1 should be: 0.00532 
Value 2 should be: 0.051960 
Value 3 should be: 0.0067124 

사람은 아직 소수의 수를 처리 할 수있는 기능에 이상을 달성하는 간단한 방법을 알고 있나요 ?

감사합니다.

+5

부동 소수점은 10 진수로 내부적으로 표현되지 않지만 2 진수입니다. 결과적으로 '0.1'은 예를 들어 * 표현 가능 플로트가 아닙니다. 그것은'0.099999 ... ish 또는'0.1000 ...'ish와 근사치입니다. 그래서 그것은 대단히 불안정합니다. –

+0

관련 : https://stackoverflow.com/questions/588004/is-floating-point-math-broken –

+1

정말로 이것을 원한다면 float이 아닌 표현으로 전환해야합니다 (예 : 숫자와 함께 정수 소수 자릿수를 제공). –

답변

1

표준 모듈 decimal을 보았습니까?

부동 소수점 동작을 우회합니다.

할 수있는 것을 설명하기 만하면됩니다.

0.00532 
0.051960 
0.0067124 
2 
0.05200 
를 인쇄

import decimal 
my_number = '0.00531' 
mnd = decimal.Decimal(my_number) 
print(mnd) 
mnt = mnd.as_tuple() 
print(mnt) 
mnt_digit_new = mnt.digits[:-1] + (mnt.digits[-1]+1,) 
dec_incr = decimal.DecimalTuple(mnt.sign, mnt_digit_new, mnt.exponent) 
print(dec_incr) 
incremented = decimal.Decimal(dec_incr) 
print(incremented) 

인쇄

0.00531 
DecimalTuple(sign=0, digits=(5, 3, 1), exponent=-5) 
DecimalTuple(sign=0, digits=(5, 3, 2), exponent=-5) 
0.00532 

또는 전체 버전 (편집도 어떤 자리를 운반, 그래서 그것은 또한 '0.199'에서 작동 후) ...

from decimal import Decimal, getcontext 

def add_one_at_last_digit(input_string): 
    dec = Decimal(input_string) 
    getcontext().prec = len(dec.as_tuple().digits) 
    return dec.next_plus() 

for i in ('0.00531', '0.051959', '0.0067123', '1', '0.05199'): 
    print(add_one_at_last_digit(i)) 

+0

이것 역시 훌륭했습니다! 고맙습니다. :) – dAJVqgVFsB

0

다른 의견 작성자는 주의 : 주어진 숫자 0.1234이 내부 표현으로 변환되어 더 이상 원하는 방식으로 처리 할 수 ​​없기 때문에 floats을 사용해서는 안됩니다. 이것은 의도적으로 모호하게 공식화되었습니다. 부동 소수점 자체에 대한 주제입니다. This article은 주제를 매우 잘 설명하며 주제에 대한 좋은 입문서입니다.

그런데 일 수 있습니다. 대신 입력을 문자열로 사용하는 것입니다 (예 : 입력에서 읽을 때이를 float로 변환하지 않음). 그런 다음 당신이 할 수 있습니다 :

from decimal import Decimal 

def add_one(v): 
    after_comma = Decimal(v).as_tuple()[-1]*-1 
    add = Decimal(1)/Decimal(10**after_comma) 
    return Decimal(v) + add 

if __name__ == '__main__': 
    print(add_one("0.00531")) 
    print(add_one("0.051959")) 
    print(add_one("0.0067123")) 
    print(add_one("1")) 

이 인쇄

0.00532 
0.051960 
0.0067124 
2 

업데이트 :

당신이 수레에서 작동 할 필요, 당신은 퍼지 논리를 사용을 시도 할 수있는 경우 긴밀한 프레젠테이션을 할 수 있습니다. , 당신이보고 그것으로 재생해야

from decimal import Decimal, Context 

def add_one_float(v): 
    v_normalized = Decimal(v).normalize(Context(prec=16)) 
    after_comma = v_normalized.as_tuple()[-1]*-1 
    add = Decimal(1)/Decimal(10**after_comma) 
    return Decimal(v_normalized) + add 

그러나 16의 정밀도가 순수 실험 대상이므로주의 해주십시오 : decimal는 원래 번호와 일치하도록 진수 표현의 정밀도를 다운 그레이드 할 수있는 normalize 기능을 제공합니다 원하는 결과가 나오는 경우 이 필요하면이 경로를 사용할 수 없습니다.

+0

@ dAJVqgVFsB 감사합니다. 그 때 내 대답을 upvote 및/또는 수락 할 수 있습니까? (그 stackoverflow에 통화 ..) – hansaplast