double
を必要な数に縮小しようとするプログラムがあります。私が得る出力はNaN
です。
JavaでNaN
はどういう意味ですか?
このページ から取得:
「NaN」は「not a number」の略です。 「Nan」は、浮動小数点演算に入力パラメーターが含まれていて、その演算によって未定義の結果が生成される場合に生成されます。たとえば、0.0を0.0で除算すると、算術的に未定義になります。負の数の平方根を取ることも未定義です。
NaN
は「数値ではない」を意味し、基本的には IEE 754浮動小数点 標準の特別な浮動小数点値の表現です。 NaN は、通常、値が有効な浮動小数点数で表現できないものであることを意味します。
変換される値が他の値である場合、たとえば、数値を表さない文字列を変換する場合、変換はこの値になります。
NaN
は「Not a Number」を意味し、たとえばゼロをゼロで除算するなど、浮動小数点数に対する未定義の演算の結果です。 (ゼロではない数値をゼロで除算することも数学では通常未定義ですが、NaNではなく正または負の無限大になります)。
NaN
は「数字ではない」という意味です。これは、演算の結果が定義されていないか、実数として表現できないことを意味する特別な浮動小数点値です。
この値の詳細については、 here を参照してください。
NaNはNot a Numberの略です。数学的に定義されていない値を示すために使用されます。 0.0を0.0で割るのと同じです。詳細については、こちらをご覧ください: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm
さらにヘルプが必要な場合は、ここにプログラムを投稿してください。
NaN =数値ではありません。
数字ではないことを意味します。これは、多くのプログラミング言語で不可能な数値を表す一般的な表現です。
Javaの男ではありませんが、JSや他の言語では "Not a Number"を使用しています。これは、何らかの操作によって有効な数字にならないことを意味します。
文字通り「数字ではない」という意味です。変換プロセスに問題があると思われます。
このリファレンス のNot A Numberセクションをご覧ください
有効な浮動小数点値ではありません(例:ゼロ除算の結果)
最小限の実行可能な例
最初に知っておくべきことは、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));
}
}
GitHub上流 。
で実行:
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で公開されているとは思わない: Why by integer division by zero 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でテスト済み。