2011-08-17 1 views
0

두 개의 float, ab이 있다고 가정하고 "대략 동일"한 경우에만 다음 작업과 비슷하거나 정확하게 문제가 될 수 있습니까?C#에서 둥근 수레가 신뢰할만한 결과를 생성합니까?

예 : 또는

Math.Round(a) == Math.Round(b) 

, 방법은 가장 가까운 정수로에 안정적으로 그 라운드가? 위의 방법으로 문제가 해결되지 않으면 간단히 (int)Math.Round(a)을 수행하는 것이 신뢰할 수 없다고 가정합니다.

편집 : 나는이 같은 답변을 얻을 것이라고 예측 했어야했지만 두 값의 '친밀감'을 확인하려고하지는 않습니다. 위의 논리가 옳다 고 가정하면, 위의 작업이 수행 될지, 아니면 3.0 == 3.0001과 같은 것을 얻을 수있는 기회가 있습니까?

+0

아마도 관련 : http://stackoverflow.com/questions/6683059/are-floating-point-numbers-consistent-in-c-can-they-be/6685966#6685966 – CodesInChaos

+0

나는 당신이 정말로 당신을 이해하지 않습니다. 하고 싶은/당신의 질문은 무엇입니까. – CodesInChaos

+0

당신이 신경 쓰는 사람이 거의 비슷하다면 두 가지의 'Math.Abs' 차이를 여러분이 선택한 공차와 비교할 수 있습니다. – V4Vendetta

답변

3

아무 것도 작동하지 않습니다. 아주 비슷한 숫자가 다른 숫자로 반올림되는 경우 항상 경계가 명확합니다.

첫 번째 예에서는 a = 0.4999999 및 b = 0.5000001을 생각해보십시오. 아주 가깝지만 다른 정수로 바뀔 것입니다.

숫자가 큰 경우 정수로 반올림해도 아무런 효과가 없습니다. 그리고 아주 가까운 (상대적) 숫자조차도 이미 절대적인 차이가 1보다 클 것입니다. 당신은 결정론에 대해 신경 경우


, 당신은 floatdouble로 운입니다. 당신은 단지 .net에서 결정 론적 인 것을 얻을 수 없습니다. Decimal을 사용하십시오.

+0

이 질문의 목적을 위해 나는 이것을 신경 쓰지 않는다. 처리하는 동안 추가 정밀도가 필요하기 때문에 float로 저장해야하지만 결국에는 가장 가까운 정수가 중요합니다. 나는 두 값의 '근접성'을 측정하려하지 않습니다. –

0

Floor 또는 Ceieling 메서드를 사용하여 값을 반올림 할 수 있습니다. 그 훨씬 느리지 만

3

당신이 정말로 원하는 경우가 신뢰할 수있는 당신이 ... ... float 대신 Decimal를 사용해야합니다

편집 : ((int)Math.Round(a)) == ((int)Math.Round(b))

당신이 문제를 방지 3.0 == 3.0001하지만 다른 모든 함정은 귀하의 게시물을 언급하고 대답은 여전히 ​​적용됩니다 ...

로직을 좀 더 신뢰성있게 만들려고 복잡하게 만들 수 있습니다 (아래의 예제는 어떤 방법으로 잘 포장 될 수 있음)하지만 절대하지 않을 것이다 정말 믿을 만하다.

// 1 = near, 2 = nearer, 3 = even nearer, 4 = nearest 

int HowNear = 0; 

if (((int)Math.Round(a)) == ((int)Math.Round(b))) 
    HowNear++; 

if (((int)Math.Floor(a)) == ((int)Math.Floor(b))) 
    HowNear++; 

if (((int)Math.Ceiling(a)) == ((int)Math.Ceiling(b))) 
    HowNear++; 

if (Math.Round(a) == Math.Round(b)) 
    HowNear++; 
+0

두 숫자가 얼마나 가까운 지 알 수있는 이상한 방법이있는 것 같습니다. 이 방법을 사용하는 이유에 대해 저는 분명하지 않습니다. – ForbesLindesay

+0

이 방법은 일종의 "상대 친밀도 분류"입니다. OP를 이해 했으므로 차이를 측정하고 싶지 않으며 그 차이 자체가 "부동 정밀도 문제"의 대상이됩니다 ... – Yahia

+0

예,하지만 확실합니다 그 차이를 측정 한 다음 4 가지 범주의 친밀도 (예 : Math.Round (Math.Abs ​​(ab) * 5))로 그룹화하려는 경우 임의의 그룹으로 나누는 것이 좋습니다. 이렇게하면 비슷한 결과가 나타납니다. 0은 가장 가깝고 5는 당신의 예에서 Near의 점수와 다소 비슷합니다.) 그것은 덜 친밀한 척도를 제공하지 않습니까? – ForbesLindesay

0

"거의 동일한는"실제로 대답하는 pseudoexample :

double tollerance = 0.03; 

if(Math.Abs(a-b)<=tollerance) 
    // these numbers are equal ! 
else 
    //non equal 

편집

또는 당신은 더 많은 "정확한"가 되길 원한다면 :

int aint = (int)(a*100); // 100 is rounding tollerance 
int bint = (int)(b*100); // 100 is rounding tollerance 

이상,

이후
if(Math.Abs(aint -bint)<=tollerance) // tollerance has to be integer in this case, obviously 
    // these numbers are equal ! 
else 
    //non equal 
1

정수로 더블/플로트 변환하는 올바른 방법은 다음과 같습니다

(int)Math.Round(a) 

이 항상 어떤지를 테스트 할 수 있습니다 정수를 얻을 것이다 일을하는 데. 숫자가 거의 정수가되는 경우 (예 : 6.0/3.0의 결과) 그러면 큰 효과를 볼 수 있습니다. 복식/수레가 거의 동일한 두 개의 번호를 확인하는 권장되는 방법은 다음과 같습니다

허용 오차는 당신이 그 (것)들을 1 개 단위 내에서 수 있도록하려면 그들이, 예를 들어, 어떻게해야 유사한 결정하는 두 값이
Math.Abs(a-b)<tolerance 

서로 1.0의 공차를 사용하면 Math.Round와 비슷한 정확도를 제공하고 결과를 비교할 수 있지만 두 정수 사이의 중간 값에 매우 근접한 두 값을 얻으면 올바르게 작동합니다.

관련 문제