double
원하는 수로 줄이려고하는 프로그램이 있습니다. 내가 얻는 출력은 NaN
.
NaN
Java에서 무엇을 의미합니까?
double
원하는 수로 줄이려고하는 프로그램이 있습니다. 내가 얻는 출력은 NaN
.
NaN
Java에서 무엇을 의미합니까?
답변:
이 페이지 에서 가져온 :
"NaN"은 "숫자가 아님"을 의미합니다. "Nan"은 부동 소수점 연산에 정의되지 않은 결과를 생성하는 입력 매개 변수가있는 경우 생성됩니다. 예를 들어 0.0을 0.0으로 나눈 값은 산술적으로 정의되지 않습니다. 음수의 제곱근을 취하는 것도 정의되지 않습니다.
NaN
비교할 때 자신과 동일하지 않은 유일한 "숫자"라는 흥미로운 속성이 있습니다. 따라서 숫자 x
가 NaN
다음과 같은 경우 일반적인 (그리고 여러 언어에서 유일한) 테스트 :boolean isNaN(x){return x != x;}
i
과 파이썬과 같은 일부 언어는 그것을 아주 잘 처리합니다 ... 그것은 java
당신 의 경우가 아닐 수도 있습니다
NaN
"숫자가 아님"을 의미하며 기본적으로 IEE 754 부동 소수점 표준 의 특수 부동 소수점 값을 나타냅니다 . NaN 일반적으로 값이 유효한 부동 소수점 숫자로 표현 될 수없는 것을 의미합니다.
예를 들어 숫자를 나타내지 않는 문자열을 변환하는 경우와 같이 변환되는 값이 다른 경우 변환은이 값을 생성합니다.
parseFloat()
나 parseDouble
? 또는 다른 것?
NaN은 Not a Number를 나타냅니다. 수학적으로 정의되지 않은 값을 나타내는 데 사용됩니다. 0.0을 0.0으로 나누는 것과 같습니다. 여기에서 자세한 정보를 찾을 수 있습니다. https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
도움이 더 필요하면 여기에 프로그램을 게시하세요.
NaN = 숫자 아님.
최소 실행 가능 예
가장 먼저 알아야 할 것은 NaN의 개념이 CPU 하드웨어에서 직접 구현된다는 것입니다.
모든 주요 최신 CPU는 부동 소수점 형식을 지정하는 IEEE 754 를 따르는 것으로 보이며 특수 부동 값인 NaN은 해당 표준의 일부입니다.
따라서 개념은 CPU에 직접 부동 소수점 코드를 내보내는 Java를 포함하여 모든 언어에서 매우 유사합니다.
계속하기 전에 먼저 내가 작성한 다음 답변을 읽어 보는 것이 좋습니다.
이제 몇 가지 Java 작업을 수행합니다. 핵심 언어에없는 관심 기능의 대부분은 내부에 java.lang.Float
있습니다.
Nan.java
import java.lang.Float;
import java.lang.Math;
public class Nan {
public static void main(String[] args) {
// Generate some NaNs.
float nan = Float.NaN;
float zero_div_zero = 0.0f / 0.0f;
float sqrt_negative = (float)Math.sqrt(-1.0);
float log_negative = (float)Math.log(-1.0);
float inf_minus_inf = Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY;
float inf_times_zero = Float.POSITIVE_INFINITY * 0.0f;
float quiet_nan1 = Float.intBitsToFloat(0x7fc00001);
float quiet_nan2 = Float.intBitsToFloat(0x7fc00002);
float signaling_nan1 = Float.intBitsToFloat(0x7fa00001);
float signaling_nan2 = Float.intBitsToFloat(0x7fa00002);
float nan_minus = -nan;
// Generate some infinities.
float positive_inf = Float.POSITIVE_INFINITY;
float negative_inf = Float.NEGATIVE_INFINITY;
float one_div_zero = 1.0f / 0.0f;
float log_zero = (float)Math.log(0.0);
// Double check that they are actually NaNs.
assert Float.isNaN(nan);
assert Float.isNaN(zero_div_zero);
assert Float.isNaN(sqrt_negative);
assert Float.isNaN(inf_minus_inf);
assert Float.isNaN(inf_times_zero);
assert Float.isNaN(quiet_nan1);
assert Float.isNaN(quiet_nan2);
assert Float.isNaN(signaling_nan1);
assert Float.isNaN(signaling_nan2);
assert Float.isNaN(nan_minus);
assert Float.isNaN(log_negative);
// Double check that they are infinities.
assert Float.isInfinite(positive_inf);
assert Float.isInfinite(negative_inf);
assert !Float.isNaN(positive_inf);
assert !Float.isNaN(negative_inf);
assert one_div_zero == positive_inf;
assert log_zero == negative_inf;
// Double check infinities.
// See what they look like.
System.out.printf("nan 0x%08x %f\n", Float.floatToRawIntBits(nan ), nan );
System.out.printf("zero_div_zero 0x%08x %f\n", Float.floatToRawIntBits(zero_div_zero ), zero_div_zero );
System.out.printf("sqrt_negative 0x%08x %f\n", Float.floatToRawIntBits(sqrt_negative ), sqrt_negative );
System.out.printf("log_negative 0x%08x %f\n", Float.floatToRawIntBits(log_negative ), log_negative );
System.out.printf("inf_minus_inf 0x%08x %f\n", Float.floatToRawIntBits(inf_minus_inf ), inf_minus_inf );
System.out.printf("inf_times_zero 0x%08x %f\n", Float.floatToRawIntBits(inf_times_zero), inf_times_zero);
System.out.printf("quiet_nan1 0x%08x %f\n", Float.floatToRawIntBits(quiet_nan1 ), quiet_nan1 );
System.out.printf("quiet_nan2 0x%08x %f\n", Float.floatToRawIntBits(quiet_nan2 ), quiet_nan2 );
System.out.printf("signaling_nan1 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan1), signaling_nan1);
System.out.printf("signaling_nan2 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan2), signaling_nan2);
System.out.printf("nan_minus 0x%08x %f\n", Float.floatToRawIntBits(nan_minus ), nan_minus );
System.out.printf("positive_inf 0x%08x %f\n", Float.floatToRawIntBits(positive_inf ), positive_inf );
System.out.printf("negative_inf 0x%08x %f\n", Float.floatToRawIntBits(negative_inf ), negative_inf );
System.out.printf("one_div_zero 0x%08x %f\n", Float.floatToRawIntBits(one_div_zero ), one_div_zero );
System.out.printf("log_zero 0x%08x %f\n", Float.floatToRawIntBits(log_zero ), log_zero );
// NaN comparisons always fail.
// Therefore, all tests that we will do afterwards will be just isNaN.
assert !(1.0f < nan);
assert !(1.0f == nan);
assert !(1.0f > nan);
assert !(nan == nan);
// NaN propagate through most operations.
assert Float.isNaN(nan + 1.0f);
assert Float.isNaN(1.0f + nan);
assert Float.isNaN(nan + nan);
assert Float.isNaN(nan / 1.0f);
assert Float.isNaN(1.0f / nan);
assert Float.isNaN((float)Math.sqrt((double)nan));
}
}
다음으로 실행 :
javac Nan.java && java -ea Nan
산출:
nan 0x7fc00000 NaN
zero_div_zero 0x7fc00000 NaN
sqrt_negative 0xffc00000 NaN
log_negative 0xffc00000 NaN
inf_minus_inf 0x7fc00000 NaN
inf_times_zero 0x7fc00000 NaN
quiet_nan1 0x7fc00001 NaN
quiet_nan2 0x7fc00002 NaN
signaling_nan1 0x7fa00001 NaN
signaling_nan2 0x7fa00002 NaN
nan_minus 0xffc00000 NaN
positive_inf 0x7f800000 Infinity
negative_inf 0xff800000 -Infinity
one_div_zero 0x7f800000 Infinity
log_zero 0xff800000 -Infinity
그래서 이것으로부터 우리는 몇 가지를 배웁니다.
합리적인 결과가없는 이상한 부동 연산은 NaN을 제공합니다.
0.0f / 0.0f
sqrt(-1.0f)
log(-1.0f)
를 생성합니다 NaN
.
C에서는 실제로 신호를 feenableexcept
감지하기 위해 이러한 작업에서 발생하도록 요청할 수 있지만 Java에서는 노출되지 않는다고 생각합니다. 0으로 정수 나누기 1/0으로 오류가 발생하지만 부동 소수점 1 / 0.0이 발생하는 이유는 무엇입니까? "Inf"를 반환합니까?
플러스 또는 마이너스 무한대의 한계에있는 이상한 연산은 NaN 대신 +-무한대를 제공합니다.
1.0f / 0.0f
log(0.0f)
0.0
거의이 범주에 속하지만 문제는 플러스 또는 마이너스 무한대로 갈 수 있다는 것이므로 NaN으로 남았습니다.
NaN이 부동 연산의 입력이면 출력도 NaN이되는 경향이 있습니다.
몇 가지 가능한 값이 NaN 거기에있다 0x7fc00000
, 0x7fc00001
, 0x7fc00002
, x86_64의 경우에만 생성 보이더라도 0x7fc00000
.
NaN과 무한대는 이진 표현이 비슷합니다.
그중 몇 가지를 분석해 보겠습니다.
nan = 0x7fc00000 = 0 11111111 10000000000000000000000
positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
| | |
| | mantissa
| exponent
|
sign
이것으로부터 우리는 IEEE754가 지정하는 것을 확인합니다 :
NaN은 양수 또는 음수 (상위 비트) 일 수 있지만 정상적인 작업에는 영향을주지 않습니다.
Ubuntu 18.10 amd64, OpenJDK 1.8.0_191에서 테스트되었습니다.
유효한 부동 소수점 값이 아닙니다 (예 : 0으로 나눈 결과).