ฉันมีโปรแกรมที่พยายามย่อdouble
ตัวเลขที่ต้องการ NaN
เอาท์พุทฉันได้รับคือ
อะไรNaN
หมายถึงใน Java?
ฉันมีโปรแกรมที่พยายามย่อdouble
ตัวเลขที่ต้องการ NaN
เอาท์พุทฉันได้รับคือ
อะไรNaN
หมายถึงใน Java?
คำตอบ:
นำมาจากหน้านี้ :
"NaN" ย่อมาจาก "not a number" "น่าน" เกิดขึ้นหากการดำเนินการจุดลอยตัวมีพารามิเตอร์อินพุตบางอย่างที่ทำให้การดำเนินการสร้างผลลัพธ์ที่ไม่ได้กำหนดไว้ ตัวอย่างเช่น 0.0 หารด้วย 0.0 จะไม่ได้กำหนดทางคณิตศาสตร์ การหารากที่สองของจำนวนลบก็ไม่ได้กำหนดเช่นกัน
NaN
มีคุณสมบัติที่น่าสนใจในการเป็น "ตัวเลข" เพียงตัวเดียวซึ่งไม่เหมือนกับตัวมันเองเมื่อเปรียบเทียบ ดังนั้นจึงเป็นการทดสอบทั่วไป (และในหลายภาษาเท่านั้น) หากตัวเลขx
เป็นNaN
ดังต่อไปนี้:boolean isNaN(x){return x != x;}
i
และภาษาบางอย่างเช่นการจัดการหลามเป็นอย่างดีกับมัน ... มันอาจจะไม่ได้ในกรณีที่java
ท่าน
NaN
หมายถึง“ ไม่ใช่ตัวเลข”และโดยพื้นฐานแล้วเป็นตัวแทนของค่าทศนิยมพิเศษในมาตรฐานจุดลอยตัว IEE 754 NaNโดยทั่วไปหมายความว่าค่าเป็นสิ่งที่ไม่สามารถแสดงด้วยตัวเลขทศนิยมที่ถูกต้อง
การแปลงจะทำให้เกิดค่านี้เมื่อค่าที่ถูกแปลงเป็นอย่างอื่นตัวอย่างเช่นเมื่อแปลงสตริงที่ไม่ได้แสดงถึงตัวเลข
parseFloat()
หรือparseDouble
? หรืออย่างอื่น?
NaN
หมายถึง "ไม่ใช่ตัวเลข" และเป็นผลมาจากการดำเนินการที่ไม่ได้กำหนดบนตัวเลขทศนิยมเช่นการหารศูนย์ด้วยศูนย์ (โปรดทราบว่าในขณะที่การหารจำนวนที่ไม่ใช่ศูนย์ด้วยศูนย์มักไม่ได้กำหนดไว้ในคณิตศาสตร์ แต่ก็ไม่ได้ส่งผลให้เป็น NaN แต่เป็นค่าอนันต์บวกหรือลบ)
NaN
หมายถึง "ไม่ใช่ตัวเลข" เป็นค่าทศนิยมพิเศษซึ่งหมายความว่าผลลัพธ์ของการดำเนินการไม่ได้กำหนดไว้หรือไม่สามารถแสดงเป็นจำนวนจริงได้
ดูที่นี่สำหรับคำอธิบายเพิ่มเติมของค่านี้
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
ซีพียูสมัยใหม่ที่สำคัญทั้งหมดดูเหมือนจะเป็นไปตามIEEE 754ซึ่งระบุรูปแบบทศนิยมและ NaN ซึ่งเป็นเพียงค่าลอยพิเศษเป็นส่วนหนึ่งของมาตรฐานนั้น
ดังนั้นแนวคิดจะคล้ายกันมากในทุกภาษารวมถึง Java ซึ่งเพียงแค่ปล่อยรหัสทศนิยมโดยตรงไปยัง CPU
ก่อนดำเนินการต่อคุณอาจต้องอ่านคำตอบต่อไปนี้ที่ฉันเขียนไว้ก่อน:
ตอนนี้สำหรับการดำเนินการบางอย่างของ 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: ทำไมการหารจำนวนเต็มด้วยศูนย์ 1/0 จึงให้ข้อผิดพลาด แต่ทศนิยม 1 / 0.0 ส่งคืน "Inf"?
การดำเนินการแปลก ๆ ที่อยู่ในขีด จำกัด ของบวกหรือลบอินฟินิตี้อย่างไรก็ตามให้ + - อินฟินิตี้แทน NaN
1.0f / 0.0f
log(0.0f)
0.0
เกือบจะอยู่ในหมวดหมู่นี้ แต่ปัญหาน่าจะเป็นไปได้ว่ามันอาจจะไปที่บวกหรือลบอินฟินิตี้ดังนั้นมันจึงถูกปล่อยให้เป็น NaN
หาก NaN เป็นอินพุตของการดำเนินการแบบลอยเอาต์พุตก็มีแนวโน้มที่จะเป็น NaN
มีค่าที่เป็นไปได้หลายน่าน0x7fc00000
, 0x7fc00001
, 0x7fc00002
แม้ว่า x86_64 0x7fc00000
ดูเหมือนว่าจะสร้างเพียง
NaN และ infinity มีการแทนเลขฐานสองที่คล้ายกัน
มาแบ่งย่อยบางส่วน:
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
ไม่ใช่คน Java แต่ใน JS และภาษาอื่น ๆ ฉันใช้ "ไม่ใช่ตัวเลข" ซึ่งหมายความว่าการดำเนินการบางอย่างทำให้มันกลายเป็นตัวเลขที่ไม่ถูกต้อง
หมายถึง "ไม่ใช่ตัวเลข" อย่างแท้จริง ฉันสงสัยว่ามีบางอย่างผิดปกติกับกระบวนการแปลงของคุณ
ตรวจสอบส่วนไม่ใช่ตัวเลขที่ข้อมูลอ้างอิงนี้
ไม่ใช่ค่าทศนิยมที่ถูกต้อง (เช่นผลลัพธ์ของการหารด้วยศูนย์)