2016-09-01 5 views
0

말하자면, 어떤 정수 n이 있고 어떤 비율에 따라 두 개의 다른 정수로 나누고 싶습니다. 나는 그것이 작동하는지 아닌지 스스로에게 묻는 접근법을 가지고있다.비율에 따라 두 개의 정수를 분배합니다.

예 : 비율 70 인 20은 14,6으로 세분해야합니다.

확실한 해결책은 다음과 같습니다

int n = 20; 
double ratio = .7; 
int n1 = static_cast<int>(n * ratio); 
int n2 = static_cast<int>(n * (1 - ratio)); 

캐스트는 항상 floor들 때문에,하지만, 난 보통 내 결과를 과소 평가. std::round을 사용하는 경우 여전히 작동하지 않는 경우가 있습니다. 예를 들어, 소수 첫째 자리가 5 인 경우 두 숫자는 반올림됩니다.

일부 동료는 다음과 같이 제안했습니다. Ceil은 첫 번째 숫자이고 Floor는 두 번째 숫자입니다. 그러나 대부분의 테스트에서 다음과 같이 작동합니다.

1) 자연스럽게 발생하는 회계상의 반올림 오류를 실제로 처리합니까? 내가 생각하는 것 : 20 * .7은 14 일 수 있지만 20 * .3은 5.999999 일 수 있습니다. 그래서, 내 합계는 14 + 5 = 19 일 수도 있습니다. 그러나 이것은 단지 내 추측이지만 이러한 종류의 결과가 발생할 수 있는지 여부는 알 수 없습니다. 그렇지 않으면 이러한 종류의 반올림 제안이 효과가 없을 것입니다.

2) 작동하더라도 ... 왜?

(난 그냥 n 개의 * 비율로 1 위를 계산하고 n으로 숫자 2를 계산할 수 염두에두고 - N * 비율,하지만 난 아직이 질문에 대한 답에 관심이있을 것입니다)

+1

왜 'n1 + n2 == n'이라면 반올림 한 다음에 간단히 덧셈/뺄셈을하고, 필요하다면 하나를 더하거나 뺍니다. – user463035818

+3

부동 소수점 - 정수 변환은 'ceil'이 아니고'floor '입니다. –

+1

당신은 어떤 종류의 반올림 조합이 작동하지 않는다는 것을 증명하는 예제. 그리고 당신은 뺄셈 방법이 효과가 있다는 것을 압니다. 그래서 당신의 질문은 무엇입니까? – michalsrb

답변

1

는 의심을 확인하고 천장을 만들다 + 바닥 방법은 항상 작동하지 않는 것을 보여줍니다 예입니다. 그것은 컴퓨터에서 부동 소수점 숫자의 유한 정밀도에 의해 발생 :

#include <iostream> 
#include <cmath> 

int main() { 
    int n = 10; 
    double ratio = 0.7; 
    int n1 = static_cast<int>(floor(n * ratio)); 
    int n2 = static_cast<int>(ceil(n * (1.0 - ratio))); 

    std::cout << n1 << " " << n2 << std::endl; 
} 

출력 :

7 4 

7 + 4 (11)이기 때문에 잘못입니다.

+0

(오, 죄송합니다. 답장을 보내주십시오. 무시하십시오.) –

2

방법에 대한 이? 여기

int n = 20; 
double ratio = .7; 
int n1 = static_cast<int>(n * ratio); 
int n2 = n - n1; 
+0

이것은 확실히 작동합니다. 그러나 요청자는 이미이 솔루션을 알고 있다고 썼습니다 ... – michalsrb

+0

@michalsrb 정확히 그가 그걸 말 했나요? – ToniBig

+0

@ToniBig 이것은 편집이었고 마지막 단락에서 언급했습니다. 그럼에도 불구하고, 나의 질문은 1)과 2) 앞에 선다. 제목이 오도 된 것 일지라도 나는 배포판 자체에 대한 해결책을 요구하지 않았다. – IceFire

0

해결책이 항상 작동하지 않는 경우 비율이 77 %이면 15와 4를 얻게됩니다 (See on coliru).

수치 해석 분야에 오신 것을 환영합니다.

먼저 컴퓨터가 부동 소수점을 완벽하게 저장할 수있는 것은 아닙니다. 위의 예에서 알 수 있듯이 은 0.77000000000000001776 (2의 거듭 제곱으로 숫자에 접근하는 방식)으로 저장됩니다.

부동 소수점 계산을 수행 할 때 항상 정밀도가 떨어집니다. std::numeric_limits<double>::epsilon()으로이 정밀도를 얻을 수 있습니다.

또한 부동 소수점 숫자를 정수로 변환 할 때 더 많은 정밀도 손실이 발생하며, 그 차이가 너무 커서 일관성없는 결과를 얻을 수 없습니다.

@ToniBig에서 제공 한 솔루션과 마지막 문장은이 손실을 숨기고 일관된 데이터를 유지한다는 장점이 있습니다.

관련 문제