2012-01-05 3 views
3

나는 다음과 같은 어리석은 기능 here 건너 온 : 인 Math.random()는 반환 이후 "두 배,는 이상한 이중 반올림 문제는

요약
public static String findOutWhatLifeIsAllAbout() { 
    int meaning = 0; 
    for (int i = 0; i < 10; i++) { 
     for (int j = 0; j < 20; j++) { 
     for (int k = 0; k < 300; k++) { 
      for (int m = 0; m < 7000; m++) { 
      meaning += Math.random() + 1; 
      } 
     } 
     } 
    } 
    return String.valueOf(meaning).replaceAll("0*$", ""); 
} 

가 예상되는 결과는 문자열"42 "입니다보다 크거나 같음 0.0 미만 1.0 "입니다. 실제로 Ubuntu에서 i5를 실행하면 결과 문자열은 "420000011", "420000008"과 유사합니다! (때로는 의미 인 Math.random()의 결과가

가 (더블 값의 어떤 종류가 인 Math.random 야기에 그립을 받으실 수 있습니다! 반올림지고)의 결과를 어떻게 든 라운드 1로, 나는 몇 가지 예를 볼 것으로 예상, 대신이 기능을 시도했다.

public static String findOutWhatLifeIsAllAboutAltered() { 
    int meaning = 0; 
    for (int i = 0; i < 10; i++) { 
     for (int j = 0; j < 20; j++) { 
     for (int k = 0; k < 300; k++) { 
      for (int m = 0; m < 7000; m++) { 
      double randomResult = Math.random(); 
      int converted = randomResult; 

      if (converted > 0) { 
       System.out.println("Misbehaving double = " + randomResult); 
      } 

      meaning += converted + 1; 
      } 
     } 
     } 
    } 
    return String.valueOf(meaning).replaceAll("0*$", ""); 
} 

그러나이 제제는 항상 사람이 왜 변경된 기능의 동작 변경? 감사합니다.

또한 이유에 대한 통찰력을 제공 할 수 있습니다 "42!"반환 자바는 원래의 기능을 사용하게한다. n 컴파일은 전혀? += 호출에서 정밀도 상실 오류가 발생하지 않아야합니까?

편집 코드를 게시했습니다. 여러분 모두가보고 싶었습니다. "원래"버전에는 캐스트가 있어야하지 않았습니다.

+2

이것을 컴파일하는 Java 버전은 무엇입니까? 나는 이것을 시험해 보았고 Java 1.6을 사용하여 정답을 제시한다. – Yuushi

+0

또한 내 시스템 (OS X의 Java 1.6)에서 두 함수 모두''42 "'를 반환합니다. –

+0

첫 번째 예가 "수정되었습니다". int에 던지기로되어 있지 않았습니다. 이 코드는 컴파일되어 예기치 않은 결과를 보여줍니다. –

답변

2

,

meaning += Math.random() + 1; // link 

대, 그것은 심각한 버그입니다. 여기

Math.random()의 결과를 명시 적으로 캐스팅 int 0 해야 결과 즉, 다음 1이어서 meaning에 첨가되는 1 결과 추가된다. Math.random()의 결과가 충분히 가까운 경우

링크 된 포스트의 코드는, 그러나, 이제 기본적으로 meaning에 그 1과

meaning = (int)(Math.random() + (double)1 + (double)meaning); 

Math.random()의 결과를 추가 한 후 int에 대한 암시 적 캐스트를 수행 1.0의 경우 가끔 double의 결과가 반올림 됨으로써 즉시 예상보다 약간 큰 최종 결과가 생성되는 경우가 있습니다.

1

+ = 호출시 정밀도 상실 오류가 발생하지 않아야합니까? 첫 번째 경우에

번호, 당신은 명시 적으로 intMath.random()에 의해 반환되는 값을 캐스팅하고 있습니다. 두 번째 경우는 meaning, converted1은 모두 정수입니다.


있다, 그러나, 손실의 정밀도 가능한이 라인에서 : 모든 그들이 때문에 정밀 오류의 손실이되지 않습니다

int converted = randomResult; 

http://ideone.com/1ZTDi

+0

나는 그가 정밀도의 손실이 라인에서 왔음을 의미한다고 생각한다. 반드시 그 연산이 아니어야한다 - 특히 Math.random()에 의해 반환 된 double에서 나온 (int) 캐스트는 정밀도가 떨어질 것이다. 0 –

+0

'double'에서'int'로 명시 적으로 캐스팅하는 것은 정밀도의 손실 가능성 때문에 절대로 컴파일되지 않습니다. –

1

이 예제에서 모든 ints - 당신은 실제로 double을 추가하지 않습니다!

Math.random()의 결과를 int로 캐스팅 할 수있는 유일한 행이므로 두 개의 int를 함께 추가하는 것입니다. JLS는 사업자의 이러한 유형의 암시 적 캐스트를 정의하기 때문에

그러나 int로 두 배를 추가하는 경우에도 다음 아직 없을 것이다 :

양식 E1 영업 이익의 복합 대입 식 = E2는 E1 = (T) ((E1) op (E2))와 등가이며, 여기서 T는 E1이 한 번만 평가된다는 점을 제외하고는 E1의 유형입니다.

출처 : 당신이 유형 변환하고있는 것처럼 정밀 http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.2

+0

나는 그가이 줄에서 정밀도의 상실을 의미한다고 믿는다 : mean + = (int) Math.random() + 1; –

+0

캐스트가 거기에 있다고 생각하면, 그는 여전히 그가 함께 추가하는 2 개의 정수입니다! – berry120

+0

추가가 정밀도의 손실을 일으키지 않습니다 (나는 그가 그 중 하나를 제안한다고 생각하지 않습니다). –

0

손실 만이 라인에 올 수 : 인 Math.random (AS

double randomResult = Math.random(); 
int converted = randomResult; 

을)를 더블 반환0.0이고, .은 제외하고, var ible 으로 변환 될 때만 0을 포함합니다. 이중> INT의 캐스팅에 대한 자세한 내용은

여기를 참조 : 나는 맥 OS X (사자)에서 실행되는 자바 6 시스템에 원래의 프로그램을 시도했습니다 Different answer when converting a Double to an Int - Java vs .Net

와 만 (42)를 출력한다 JRE/JDK를 사용하고 있습니까?

meaning += (int)Math.random() + 1; // StackOverflow 

여기에 게시 코드가 42 만 아무것도를 출력하는 경우 링크의 코드와 원래는 여기에 게시 코드 사이의 작지만 중요한 차이가있다