복붙노트

[RUBY-ON-RAILS] 루비의 BigDecimal 전성 검사 (부동 소수점 newb)

RUBY-ON-RAILS

루비의 BigDecimal 전성 검사 (부동 소수점 newb)

내 루비의 BigDecimal 유형 (심지어 정밀도와 스케일 다양한 길이와)과 정확하게 계산해야한다 또는 나는 점 헛소리를 떠 예상해야 올바른 이해되어 있습니까?

레일 응용 프로그램 내에서 내 모든 값의 BigDecimal의 유형과 내 개체 유형을 그냥 내 방식의 희망이 아니라, 몇 가지 오류 (서로 다른 소수의 길이가 수행)을보고 있어요.

해결법

  1. ==============================

    1.부동 소수점 연산 작업 할 때 두 가지 일반적인 함정이있다.

    부동 소수점 연산 작업 할 때 두 가지 일반적인 함정이있다.

    첫 번째 문제는 루비 부동 소수점 정밀도를 해결 한 것입니다. 실제로이 중 하나를 사이에 당신이나 재앙 2), 3) 무엇인가에 대한 문제 1) 수 없습니다. 다음을 고려하세요:

    # float
    1.0e+25 - 9999999999999999900000000.0
    #=> 0.0
    
    # bigdecimal
    BigDecimal("1.0e+25") - BigDecimal("9999999999999999900000000.0")
    #=> 100000000
    

    1 억의 정밀도 차이! 꽤 심각한, 맞죠?

    정밀도 오차는 원래 수의 0.000000000000001 %에 대해 제외. 정말이 문제인지 아닌지를 결정하는 것은 여러분의 몫입니다. 그러나 문제는 임의의 정밀도를 가지고 있기 때문에 BigDecimal를 사용하여 제거된다. 유일한 제한은 루비에서 사용할 수있는 메모리입니다.

    두 번째 문제는 부동 소수점 정확하게 모든 분수를 표현할 수 있다는 것입니다. 루비 (대부분의 다른 언어)의 수레 이진 부동 점 때문에 특히, 그들은 소수가 문제가있다. 예를 들어, 소수 부분는 0.2 영원히 반복되지 이진 분획 (0.001100110011 ...)이다. 이것은 이진 부동 소수점에 정확하게 저장 될 수 없다, 더 정밀도가 무엇인지는 중요하지 않습니다.

    당신이 숫자를 반올림 할 때 이것은 큰 차이를 만들 수 있습니다. 치다:

    # float
    (0.29 * 50).round
    #=> 14  # not correct
    
    # bigdecimal
    (BigDecimal("0.29") * 50).round
    #=> 15  # correct
    

    BigDecimal를 정확하게 소수의 분수를 설명 할 수 있습니다. 그러나, 어느 소수 분획 정확하게 설명 될 수없는 분획있다. 예를 들면 1/9 (0.1111111111111 ...)이 영원히 반복되지 소수 부분이다.

    당신이 숫자를 반올림 때 다시, 이것은 당신을 물린 것입니다. 치다:

    # bigdecimal
    (BigDecimal("1") / 9 * 9 / 2).round
    #=> 0  # not correct
    

    이 경우, 여전히 반올림 오류를 줄 것이다 소수점 부동 포인트를 사용하여.

    어떤 결론 :

  2. from https://stackoverflow.com/questions/3039650/ruby-bigdecimal-sanity-check-floating-point-newb by cc-by-sa and MIT license