2013-03-06 4 views
-3

cplex.getvalue (x)는 float 값을 반환하고 int에 값을 넣으면 처음 것과 다릅니다. 정수 변수의 값에 액세스하는 더 좋은 방법이 있습니까? C++을 통해 정확한 정수 변수 값에 액세스

지금 난 그냥 순진 방법을 사용하고 (예 : int 등)을, 당신이가는 필수 유형의 부동 소수점 값을 저장하는 경우 나는

val = cplex.getObjValue() + 0.1; 

for (int i = 0; i < n; i++) 
    returnX[i] = cplex.getValue(x[i]) + 0.1; 
+0

여기서'0.1'은 무엇이라고 생각하십니까? 나는 그것이 당신의 "순진한 길"이라고 생각합니다. –

+0

나는 이걸로 무엇을 하려는지 잘 모르겠다. –

+0

나는 0.5를 사용해야한다는 것을 알고있다. 그러나 나는 왜 내가 사용하는지 알지 못한다. – snowying

답변

3

그것을 잘인지 모르거나하지 않는다 소수점 이하의 정밀도를 잃어 버린다. 정수형은 단순히 정수 만 저장합니다. intfloat을 저장하면 소수점 이하의 값은 모두 손실됩니다.

float에 0.1을 더하면 원래 값보다 약 0.1 큰 부동 소수점 값을 얻게됩니다. 이것을 int에 할당하면 똑같은 문제가 발생합니다. 당신은 단지 다른 값을자를 것입니다.

정밀도를 유지하려면 float이 필요하면 float (또는 더 높은 정밀도는 double)에 저장하십시오.

원래 int 한 가치가 당신이 마지막에 얻을 값이 아니라 그런 일이 방금 무슨 다른 int입니다 당신이 int -> float -> int 같은 변환을하고 아마도합니다. float으로의 변환은 대칭이 아닙니다. int ~ float 변환은 가장 가까운 표현 가능 float 값으로 변환되지만 float ~ int 변환은 잘립니다.

부동 소수점 유형의 prvalue는 정수 유형의 prvalue로 변환 될 수 있습니다. 변환이 잘립니다. 즉, 분수 부분은 폐기됩니다. [...]

정수형 또는 유효 범위가없는 열거 형의 prvalue는 부동 소수점 유형의 prvalue로 변환 될 수 있습니다. 가능하면 결과는 정확합니다. 변환 될 값이 표현할 수있는 값의 범위 내에 있지만 그 값을 정확하게 나타낼 수없는 경우, 다음에 더 낮은 또는 더 높은 표현 가능한 값을 구현 정의 된 선택입니다. [...]

이 해결책은 중간으로 변환하지 말아야합니다. float. int을 원하면 int으로 유지하십시오. 웬일인지 계산하는 것이 int이라는 사실에도 불구하고 함수가 float을 반환하는 것이 의미가있는 경우 그 결과를 받아 들여야합니다.

+0

'int'가 숫자 내에있는 한 'float'에있는 비트 수 (일반적으로 23 비트이므로 약 8million이 제대로 작동하고 최대 1620만이 잘 동작 할 것입니다.) 'float'에 저장하지 않아도 아무 것도 손실되지 않습니다. 그러나 일부 수학이 실수 (덧셈, 뺄셈, 곱셈 또는 나눗셈)로 끝나면 그 값은 비트를 잃거나 얻을 수 있으므로 모든 수학이 정확히 smae 수로 나타나더라도 더 이상 원래 값으로 되돌릴 수 없습니다 . –

+0

int와 float에 대한 자세한 설명을 주셔서 감사합니다. 실제로 코드가 실제로 어떻게 작동하는지 아는 것이 좋습니다. cplex를 사용합니까? 실제로 그것은 정수 값을 직접 반환하는 함수가 있어야한다고 생각합니다. – snowying

1

첫째, int로 변환 할 때 정밀도 값을 잃게됩니다. 값을 반올림하면됩니다.

예 :

float fVal = 10.89; 

int nVal = (fVal > 0.0) ? (fVal + 0.5) : (fVal - 0.5); 
+0

깔끔한 코드 주셔서 감사합니다! – snowying

+0

No Prob. 그냥 위로 투표 : D – CasperGhost

0

C++은 (대신 반올림 반올림)는 0을 향해 라운딩 및 플로트가 aproximate 값을 저장할 수 있기 때문에 정확하지 않을 수있는 있기 때문에 (예 0.9999997f) 당신은 당신이 마주 치고있는 결과를 얻습니다.

+0.001을 추가하는 것이 좋습니다.가장 가까운 쪽을 반올림하고 싶다면 0.5f를 더한 다음 C++이 그 내용을 반올림하도록합시다.

float closerToFive = 5.454f; 
float closerToSix = 5.545f; 

int five = static_cast<int>(closerToFive + 0.5f); 
int six = static_cast<int>(closerToSix + 0.5f); 

"순진한 방법"일 수도 있지만 잘 작동합니다. 당신이 많이 그것을 할 경우 FUNC에 랩 :

constexpr int ftoi(float value) 
{ 
    return static_cast<int>(value + (value > 0.0f? 0.5f : -0.5f)); 
} 


ftoi(5.454f) -> 5 
ftoi(5.545f) -> 6 
ftoi(-5.454f) -> -5 
ftoi(-5.545f) -> -6 

http://ideone.com/gDT4GP

편집 :이 CasperGhost의 대답에서 알 수 있듯이, 계정 부정적인 수레에 걸릴 잊으. ftoi() 함수가 수정되었습니다.

+0

고마워, 순진한 방법으로 문제가 없어야합니다! – snowying

+0

제가 알고있는 것은 아니지만 부동 소수점 연산에 대한 전문가는 아닙니다. –