ความแตกต่างระหว่างทศนิยมทศนิยมและสองเท่าใน. NET?


2085

อะไรคือความแตกต่างระหว่างdecimal, floatและdoubleใน .NET?

เมื่อไหร่จะมีคนใช้อย่างใดอย่างหนึ่งเหล่านี้?


1
บทความที่น่าสนใจzetcode.com/lang/csharp/datatypes
GibboK

ที่เกี่ยวข้อง: sandbox.mc.edu/~bennet/cs110/flt/dtof.html
Pacerier

คำตอบ:


2266

floatและdoubleจะลอยไบนารีประเภทจุด กล่าวอีกนัยหนึ่งมันเป็นตัวแทนของตัวเลขเช่นนี้:

10001.10010110011

หมายเลขไบนารี่และตำแหน่งของจุดไบนารี่ถูกเข้ารหัสทั้งคู่ภายในค่า

decimalเป็นลอยทศนิยมชนิดจุด กล่าวอีกนัยหนึ่งมันเป็นตัวแทนของตัวเลขเช่นนี้:

12345.65789

อีกครั้งหมายเลขและที่ตั้งของจุดทศนิยมจะถูกเข้ารหัสภายในค่านั่นคือสิ่งที่ทำให้decimalยังคงเป็นประเภทจุดลอยแทนประเภทจุดคงที่

สิ่งสำคัญที่ควรทราบคือมนุษย์จะใช้เพื่อเป็นตัวแทนที่ไม่ใช่จำนวนเต็มในรูปแบบทศนิยมและคาดหวังผลลัพธ์ที่แน่นอนในการเป็นตัวแทนทศนิยม; ไม่ใช่ทศนิยมทั้งหมดที่สามารถแทนได้ในทศนิยมทศนิยมเช่น - 0.1 ดังนั้นถ้าคุณใช้ค่าทศนิยมลอยตัวไบนารีคุณจะได้ค่าประมาณ 0.1 คุณจะยังคงได้รับการประมาณเมื่อใช้ทศนิยมทศนิยมเช่นกัน - ผลลัพธ์ของการหาร 1 ด้วย 3 ไม่สามารถแสดงได้อย่างแน่นอน

เป็นสิ่งที่จะใช้เมื่อ:

  • สำหรับค่าซึ่งเป็น "ธรรมชาติที่แน่นอนทศนิยม" decimalมันเป็นเรื่องดีที่จะใช้ สิ่งนี้มักจะเหมาะสำหรับแนวคิดใด ๆ ที่มนุษย์คิดค้นขึ้นมา: คุณค่าทางการเงินเป็นตัวอย่างที่ชัดเจนที่สุด พิจารณาคะแนนที่ให้กับนักดำน้ำหรือนักสเก็ตน้ำแข็ง

  • สำหรับค่าซึ่งเป็นสิ่งประดิษฐ์อื่น ๆ จากธรรมชาติที่ไม่สามารถวัดได้จริงๆว่าแล้วfloat/ doubleมีความเหมาะสมมากขึ้น ตัวอย่างเช่นข้อมูลทางวิทยาศาสตร์มักจะแสดงในรูปแบบนี้ ที่นี่ค่าดั้งเดิมจะไม่ "ถูกต้องทางทศนิยม" ในการเริ่มต้นดังนั้นจึงไม่สำคัญสำหรับผลลัพธ์ที่คาดหวังในการรักษา "ความแม่นยำทศนิยม" ชนิดจุดลอยตัวแบบไบนารีนั้นทำงานได้เร็วกว่าทศนิยม


58
float/ doubleมักจะไม่แสดงตัวเลขเป็น101.101110ปกติมันจะแสดงเป็นสิ่งที่ชอบ1101010 * 2^(01010010)- ตัวแทน
Mingwei ซามูเอล

79
@Hazzard: นั่นคือสิ่งที่ "และที่ตั้งของจุดไบนารี" ส่วนหนึ่งของคำตอบหมายถึง
Jon Skeet

112
ฉันประหลาดใจที่มันไม่ได้ถูกกล่าวถึงแล้วfloatเป็นคำหลัก C # และไม่ใช่ประเภท. Net มันSystem.Single.. singleและdoubleเป็นประเภทเลขฐานสองแบบลอยตัว
Brett Caswell

54
@BKSpurgeon: ดีในแบบเดียวกับที่คุณสามารถพูดได้ว่าทุกอย่างเป็นแบบไบนารี่ซึ่งมันจะกลายเป็นคำจำกัดความที่ไร้ประโยชน์ ทศนิยมเป็นประเภททศนิยมซึ่งเป็นตัวเลขที่แสดงเป็นซิกนิฟิแคนด์จำนวนเต็มและสเกลเช่นผลลัพธ์คือซิกนิฟิแคนด์ * 10 ^ สเกลในขณะที่ทริปและดับเบิลเป็นสเกลนัยสำคัญ * 2 ^ สเกล คุณใช้ตัวเลขที่เขียนเป็นทศนิยมและเลื่อนจุดทศนิยมไปทางด้านขวาจนสุดที่คุณมีจำนวนเต็มเพื่อหาค่าซิกนิแคนด์และสเกล สำหรับ float / double คุณต้องเริ่มด้วยตัวเลขที่เขียนด้วยเลขฐานสอง
Jon Skeet

21
ความแตกต่างอื่น: ลอย 32- บิต; สองครั้งที่ 64- บิต; และทศนิยม 128- บิต
เดวิด

1073

ความแม่นยำเป็นความแตกต่างหลัก

Float - 7 หลัก (32 บิต)

ดับเบิล -15-16 หลัก (64 บิต)

ทศนิยมที่สำคัญ -28-29 หลัก (128 บิต)

ทศนิยมมีความแม่นยำสูงกว่ามากและมักใช้ในแอปพลิเคชันทางการเงินที่ต้องการความแม่นยำระดับสูง ทศนิยมนั้นช้ากว่ามาก (มากถึง 20 เท่าในการทดสอบบางอย่าง) กว่าแบบ double / float

Decimals and Floats / Doubles ไม่สามารถเปรียบเทียบได้โดยไม่ต้องใช้ cast ในขณะที่ Float และ Doubles สามารถทำได้ ทศนิยมยังอนุญาตให้มีการเข้ารหัสหรือต่อท้ายเลขศูนย์

float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);

ผลลัพธ์ :

float: 0.3333333  
double: 0.333333333333333  
decimal: 0.3333333333333333333333333333

65
@ Thecrocodilehunter: ขอโทษ แต่ไม่ใช่ ทศนิยมสามารถแทนตัวเลขทั้งหมดที่สามารถแทนด้วยเครื่องหมายทศนิยม แต่ไม่ใช่เช่น 1/3 1.0m / 3.0m จะประเมินเป็น 0.33333333 ... ด้วยจำนวนที่มาก แต่ จำกัด จำนวน 3s ในตอนท้าย การคูณด้วย 3 จะไม่ส่งคืนค่า 1.0 ที่แน่นอน
Erik P.

50
@Thecrocodilehunter: ฉันคิดว่าคุณสับสนและแม่นยำ พวกมันต่างกันในบริบทนี้ ความแม่นยำคือจำนวนหลักที่มีเพื่อแสดงจำนวน ยิ่งแม่นยำยิ่งคุณต้องปัดเศษน้อย ไม่มีชนิดข้อมูลที่มีความแม่นยำไม่ จำกัด
Igby Largeman

13
@Thecrocodilehunter: คุณกำลังสมมติว่าค่าที่วัดได้นั้นแน่นอน 0.1 - นั่นไม่ค่อยเป็นเรื่องจริงในโลกแห่งความเป็นจริง! รูปแบบการจัดเก็บข้อมูลใด ๆ ที่จำกัด จะทำให้จำนวนของค่าที่เป็นไปได้ไม่สิ้นสุดเท่ากับจำนวนของรูปแบบบิตที่ จำกัด ยกตัวอย่างเช่นfloatจะ conflate 0.1และ0.1 + 1e-8ในขณะที่decimalจะ conflate และ0.1 0.1 + 1e-29แน่นอนว่าภายในช่วงที่กำหนดค่าบางอย่างสามารถแสดงในรูปแบบใดก็ได้โดยไม่มีการสูญเสียความถูกต้องเป็นศูนย์ (เช่นfloatสามารถเก็บจำนวนเต็มใด ๆ ได้ถึง 1.6e7 โดยไม่มีการสูญเสียความแม่นยำเป็นศูนย์) - แต่นั่นก็ยังไม่มีความแม่นยำไม่สิ้นสุด
Daniel Pryden

27
@Thecrocodilehunter: คุณพลาดจุดของฉัน 0.1คือไม่ได้เป็นค่าพิเศษ ! มีเพียงสิ่งเดียวที่ทำให้0.1"ดี" กว่า0.10000001เป็นเพราะมนุษย์ชอบฐาน 10 และแม้จะมีfloatค่าถ้าคุณเริ่มต้นสองค่าที่มี0.1ลักษณะเดียวกับที่พวกเขาทั้งสองจะเป็นค่าเดียวกัน มันเป็นเพียงว่าคุ้มค่าที่จะไม่เป็นว่า 0.1 - มันจะมีค่าใกล้เคียงกับ0.1floatที่สามารถแสดงว่าเป็น แน่นอนด้วยไบนารีลอย(1.0 / 10) * 10 != 1.0แต่ด้วยทศนิยมลอย(1.0 / 3) * 3 != 1.0ทั้ง ทั้งเป็นทำเลที่ดีเลิศได้อย่างแม่นยำ
Daniel Pryden

16
@Thecrocodilehunter: คุณยังไม่เข้าใจ ผมไม่ทราบว่าวิธีการพูดแบบนี้อีกเลยชัดถ้อยชัดคำ: ใน C ถ้าคุณไม่double a = 0.1; double b = 0.1;แล้วจะเป็นจริงa == b มันเป็นแค่ที่aและbจะทั้งสอง0.1ไม่ได้ว่าเท่ากับ ใน C # ถ้าคุณทำเช่นdecimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;นั้นa == bจะเป็นจริงเช่นกัน แต่ในกรณีที่ค่าของaหรือbจะว่าเท่ากับ1/3- 0.3333...พวกเขาทั้งสองจะเท่ากับ ในทั้งสองกรณีความแม่นยำบางอย่างหายไปเนื่องจากการเป็นตัวแทน คุณหัวชนฝาบอกว่าdecimalมีความแม่นยำ "อนันต์" ซึ่งเป็นเท็จ
Daniel Pryden

84

โครงสร้างทศนิยมได้รับการมุ่งเน้นอย่างเคร่งครัดเพื่อการคำนวณทางการเงินที่ต้องการความแม่นยำซึ่งค่อนข้างไม่ทนต่อการปัดเศษ ทศนิยมไม่เพียงพอสำหรับการใช้งานทางวิทยาศาสตร์อย่างไรก็ตามด้วยเหตุผลหลายประการ:

  • การสูญเสียความแม่นยำเป็นที่ยอมรับในการคำนวณทางวิทยาศาสตร์มากมายเนื่องจากข้อ จำกัด ในทางปฏิบัติของปัญหาทางกายภาพหรือสิ่งประดิษฐ์ที่วัด การสูญเสียความแม่นยำไม่เป็นที่ยอมรับในด้านการเงิน
  • ทศนิยมจะมาก (มาก) ช้ากว่าการลอยและสองเท่าสำหรับการดำเนินการส่วนใหญ่เนื่องจากการดำเนินการจุดลอยตัวจะทำในไบนารีในขณะที่สิ่งทศนิยมจะทำในฐาน 10 (เช่นลอยและคู่ถูกจัดการโดยฮาร์ดแวร์ FPU เช่น MMX / SSE ในขณะที่ทศนิยมถูกคำนวณในซอฟต์แวร์)
  • ทศนิยมมีช่วงค่าที่น้อยกว่าที่ยอมรับไม่ได้ถึงสองเท่าแม้ว่าจะสนับสนุนตัวเลขที่มีความแม่นยำมากขึ้นก็ตาม ดังนั้นทศนิยมไม่สามารถใช้แทนค่าทางวิทยาศาสตร์จำนวนมากได้

5
หากคุณทำการคำนวณทางการเงินคุณจะต้องม้วนประเภทข้อมูลของคุณเองหรือหาห้องสมุดที่ดีที่ตรงกับความต้องการของคุณ ความแม่นยำในการตั้งค่าทางการเงินนั้นถูกกำหนดโดยร่างมาตรฐาน (มนุษย์) และมีกฎเฉพาะที่แปลเป็นภาษาท้องถิ่น (ทั้งในเวลาและภูมิศาสตร์) เกี่ยวกับวิธีคำนวณ สิ่งที่ต้องการการปัดเศษที่ถูกต้องจะไม่ถูกบันทึกในประเภทข้อมูลตัวเลขใน. Net ความสามารถในการคำนวณเป็นเพียงส่วนเล็ก ๆ ของตัวต่อ
James Moore

76
+---------+----------------+---------+----------+---------------------------------------------+
| C#      | .Net Framework | Signed? | Bytes    | Possible Values                             |
| Type    | (System) type  |         | Occupied |                                             |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte   | System.Sbyte   | Yes     | 1        | -128 to 127                                 |
| short   | System.Int16   | Yes     | 2        | -32768 to 32767                             |
| int     | System.Int32   | Yes     | 4        | -2147483648 to 2147483647                   |
| long    | System.Int64   | Yes     | 8        | -9223372036854775808 to 9223372036854775807 |
| byte    | System.Byte    | No      | 1        | 0 to 255                                    |
| ushort  | System.Uint16  | No      | 2        | 0 to 65535                                  |
| uint    | System.UInt32  | No      | 4        | 0 to 4294967295                             |
| ulong   | System.Uint64  | No      | 8        | 0 to 18446744073709551615                   |
| float   | System.Single  | Yes     | 4        | Approximately ±1.5 x 10-45 to ±3.4 x 1038   |
|         |                |         |          |  with 7 significant figures                 |
| double  | System.Double  | Yes     | 8        | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
|         |                |         |          |  with 15 or 16 significant figures          |
| decimal | System.Decimal | Yes     | 12       | Approximately ±1.0 x 10-28 to ±7.9 x 1028   |
|         |                |         |          |  with 28 or 29 significant figures          |
| char    | System.Char    | N/A     | 2        | Any Unicode character (16 bit)              |
| bool    | System.Boolean | N/A     | 1 / 2    | true or false                               |
+---------+----------------+---------+----------+---------------------------------------------+

ดูที่นี่สำหรับข้อมูลเพิ่มเติม


5
คุณแยกความแตกต่างที่ใหญ่ที่สุดซึ่งเป็นฐานที่ใช้สำหรับประเภททศนิยม (ทศนิยมจะถูกเก็บไว้เป็นฐาน 10 ประเภทตัวเลขอื่น ๆ ทั้งหมดที่ระบุไว้คือฐาน 2)
BrainSlugs83

1
ช่วงค่าสำหรับ Single และ Double ไม่ได้แสดงอย่างถูกต้องในภาพด้านบนหรือโพสต์ในเวทีสนทนาต้นทาง เนื่องจากเราไม่สามารถยกข้อความได้ง่าย ๆ ให้ใช้ตัวอักษรคาเร็ต: ซิงเกิลควรเป็น 10 ^ -45 และ 10 ^ 38 และ Double ควรเป็น 10 ^ -324 และ 10 ^ 308 นอกจากนี้ MSDN ยังมีการลอยตัวในช่วง -3.4x10 ^ 38 ถึง + 3.4x10 ^ 38 ค้นหา MSDN เพื่อหา System.Single และ System.Double ในกรณีที่มีการเปลี่ยนแปลงลิงค์ โสด: msdn.microsoft.com/en-us/library/b1e65aza.aspxสองครั้ง: msdn.microsoft.com/en-us/library/678hzkk9.aspx
deegee

2
ทศนิยมคือ 128 บิต ... หมายความว่าใช้ 16 ไบต์ไม่ใช่ 12
user1477332

51

ฉันจะไม่ย้ำข้อมูลที่ดี (และไม่ดีบางส่วน) ตอบแล้วในคำตอบและความคิดเห็นอื่น ๆ แต่ฉันจะตอบคำถามติดตามของคุณด้วยเคล็ดลับ:

เมื่อไหร่จะมีคนใช้อย่างใดอย่างหนึ่งเหล่านี้?

ใช้ทศนิยมสำหรับค่าที่นับ

ใช้ float / double สำหรับค่าที่วัดได้

ตัวอย่างบางส่วน:

  • เงิน (เราจะนับเงินหรือวัดเงิน)

  • ระยะทาง (เรานับระยะทางหรือวัดระยะทางหรือไม่ *)

  • คะแนน (เราจะนับคะแนนหรือวัดคะแนนหรือไม่)

เรานับเงินอยู่เสมอและไม่ควรวัด เรามักจะวัดระยะทาง เรามักจะนับคะแนน

* ในบางกรณีสิ่งที่ฉันจะเรียกระยะทางที่ระบุเราอาจต้องการระยะทาง 'นับ' ตัวอย่างเช่นบางทีเรากำลังติดต่อกับสัญลักษณ์ของประเทศที่แสดงระยะทางไปยังเมืองต่างๆและเรารู้ว่าระยะทางเหล่านั้นไม่เคยมีทศนิยมมากกว่าหนึ่งหลัก (xxx.x km)


1
ฉันชอบคำตอบนี้มากโดยเฉพาะคำถามที่ว่า "เราจะนับหรือวัดเงิน" อย่างไรก็ตามนอกเหนือจากเงินฉันไม่สามารถคิดถึงสิ่งที่ "นับ" ซึ่งไม่ได้เป็นจำนวนเต็มเท่านั้น ฉันเห็นแอปพลิเคชั่นบางตัวที่ใช้ทศนิยมเพียงเพราะ double มีจำนวนนัยสำคัญน้อยเกินไป กล่าวอีกนัยหนึ่งอาจใช้ทศนิยมเนื่องจาก C # ไม่มีประเภทquadruple en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
John Henckel

48

float ความแม่นยำ 7 หลัก

double มีความแม่นยำประมาณ 15 หลัก

decimal มีความแม่นยำประมาณ 28 หลัก

หากคุณต้องการความแม่นยำที่ดีกว่าให้ใช้ double แทน float ในซีพียูสมัยใหม่ทั้งสองประเภทข้อมูลมีประสิทธิภาพเกือบเหมือนกัน ประโยชน์เพียงอย่างเดียวของการใช้โฟลตคือพวกเขาใช้พื้นที่น้อยลง มีความสำคัญในทางปฏิบัติหากคุณมีหลายสิ่งเท่านั้น

ฉันพบว่าสิ่งนี้น่าสนใจ สิ่งที่นักวิทยาศาสตร์คอมพิวเตอร์ทุกคนควรรู้เกี่ยวกับเลขคณิตทศนิยม


1
@RogerLipscombe: ฉันจะพิจารณาความdoubleเหมาะสมในแอปพลิเคชั่นการบัญชีในกรณีเหล่านั้น (และโดยทั่วไปเป็นเพียงกรณีเหล่านั้น) ซึ่งไม่มีประเภทจำนวนเต็มมากกว่า 32 บิตพร้อมใช้งานและdoubleถูกใช้ราวกับเป็นประเภทเลข 53 บิต (เช่นถือ จำนวนเพนนีทั้งหมดหรือหนึ่งร้อยเปอร์เซ็นต์ ทุกวันนี้ไม่ค่อยใช้สิ่งเหล่านี้มากนัก แต่หลายภาษาได้รับความสามารถในการใช้ค่าทศนิยมที่มีความแม่นยำสองเท่านานก่อนที่พวกเขาจะได้คณิตศาสตร์ 64 บิต (หรือในบางกรณีแม้แต่คณิตศาสตร์ 32 บิต!)
supercat

1
คำตอบของคุณหมายถึงความแม่นยำเป็นความแตกต่างเพียงอย่างเดียวระหว่างชนิดข้อมูลเหล่านี้ โดยปกติแล้วเลขทศนิยมแบบเลขฐานสองจะถูกนำไปใช้ในฮาร์ดแวร์ FPUประสิทธิภาพเป็นความแตกต่างที่สำคัญ นี่อาจไม่สำคัญสำหรับบางแอปพลิเคชั่น แต่มีความสำคัญอย่างยิ่งต่อผู้อื่น
saille

6
@supercat double ไม่เหมาะสมในแอปพลิเคชันการบัญชี เนื่องจาก Double สามารถประมาณค่าทศนิยมเท่านั้น (แม้จะอยู่ในช่วงของความแม่นยำของตัวเอง) นี่เป็นเพราะคู่เก็บค่าในรูปแบบฐาน -2 (ไบนารี) - ศูนย์กลาง
BrainSlugs83

2
@ BrainSlugs83: การใช้ประเภทจุดลอยตัวเพื่อเก็บปริมาณที่ไม่ใช่จำนวนเต็มจะไม่เหมาะสม แต่ในอดีตเป็นเรื่องธรรมดามากสำหรับภาษาที่มีประเภทจุดลอยตัวที่สามารถแสดงค่าตัวเลขจำนวนเต็มได้อย่างแม่นยำมากกว่าประเภทจำนวนเต็ม . บางทีตัวอย่างที่รุนแรงที่สุดคือ Turbo-87 ซึ่งมีประเภทจำนวนเต็มเท่านั้นที่ถูก จำกัด ที่ -32768 ถึง +32767 แต่RealIIRC นั้นสามารถแสดงค่าได้ถึง 1.8E + 19 ด้วยความแม่นยำของหน่วย ฉันจะคิดว่ามันจะมั่นคงมากสำหรับโปรแกรมบัญชีที่จะใช้Realเพื่อเป็นตัวแทนของจำนวนทั้งหมดของเพนนีกว่า ...
SuperCat

1
... เพื่อให้สามารถทำการคำนวณทางคณิตศาสตร์ที่มีความแม่นยำสูงโดยใช้ค่า 16 บิตจำนวนมาก สำหรับภาษาอื่น ๆ ส่วนใหญ่ความแตกต่างนั้นไม่ได้สุดขั้ว แต่เป็นเวลานานที่มันเป็นเรื่องธรรมดามากสำหรับภาษาที่ไม่มีประเภทจำนวนเต็มใด ๆ ที่เกิน 4E9 แต่มีdoubleประเภทที่มีความแม่นยำของหน่วยสูงถึง 9E15 หากต้องการเก็บตัวเลขทั้งหมดซึ่งใหญ่กว่าประเภทจำนวนเต็มที่ใหญ่ที่สุดการใช้doubleจะง่ายกว่าและมีประสิทธิภาพมากกว่าการพยายามคำนวณทางคณิตศาสตร์ที่มีความแม่นยำสูงโดยเฉพาะในขณะที่หน่วยประมวลผลมีคำสั่งให้ทำงาน 16x16-> 32 หรือ ..
supercat

36

ไม่มีใครพูดถึงเรื่องนี้

ในการตั้งค่าเริ่มต้น Floats (System.Single) และ doubles (System.Double) จะไม่ใช้การตรวจสอบโอเวอร์โฟลว์ในขณะที่ Decimal (System.Decimal) จะใช้การตรวจสอบโอเวอร์โฟลว์เสมอ

ฉันหมายถึง

decimal myNumber = decimal.MaxValue;
myNumber += 1;

พ่นOverflowException

แต่สิ่งเหล่านี้ไม่ได้:

float myNumber = float.MaxValue;
myNumber += 1;

&

double myNumber = double.MaxValue;
myNumber += 1;

1
float.MaxValue+1 == float.MaxValuedecimal.MaxValue+0.1D == decimal.MaxValueเช่นเดียวกับที่ บางทีคุณหมายถึงอะไรบางอย่างfloat.MaxValue*2?
supercat

@supercar แต่มันไม่เป็นความจริงเลยว่าทศนิยม. MaxValue + 1 ==
decimal.MaxValue

@supercar decimal.MaxValue + 0.1m == decimal.MaxValue ok
GorkemHalulu

1
การSystem.Decimalโยนข้อยกเว้นก่อนที่มันจะไม่สามารถแยกความแตกต่างของหน่วยทั้งหมดได้ แต่ถ้าแอปพลิเคชันควรจะจัดการกับเช่นดอลลาร์และเซนต์นั่นอาจจะสายเกินไป
supercat

28
  1. Double และ float สามารถถูกหารด้วยเลขจำนวนเต็มโดยไม่มีข้อยกเว้นทั้งในการคอมไพล์และรันไทม์
  2. ทศนิยมไม่สามารถหารด้วยเลขจำนวนเต็ม การรวบรวมจะล้มเหลวเสมอหากคุณทำเช่นนั้น

6
พวกเขาแน่ใจได้! พวกเขายังมีค่า "วิเศษ" สองอย่างเช่น Infinity, Negative Infinity และ NaN (ไม่ใช่ตัวเลข) ซึ่งทำให้มีประโยชน์มากสำหรับการตรวจจับเส้นแนวตั้งในขณะที่คำนวณความลาดชัน ... นอกจากนี้หากคุณจำเป็นต้องตัดสินใจว่าจะโทรลอย .TryParse, double.TryParse และฐานสิบTryParse (เพื่อตรวจสอบว่าสตริงเป็นตัวเลขหรือไม่) ฉันขอแนะนำให้ใช้ double หรือ float เนื่องจากจะวิเคราะห์คำว่า "Infinity", "-Infinity" และ "NaN" อย่างถูกต้อง ในขณะที่ทศนิยมจะไม่
BrainSlugs83

การรวบรวมล้มเหลวหากคุณพยายามหารตัวอักษรdecimalด้วยศูนย์ (CS0020) และสิ่งเดียวกันนั้นเป็นจริงของตัวอักษรอินทิกรัล อย่างไรก็ตามหากค่าทศนิยมแบบรันไทม์หารด้วยศูนย์คุณจะได้รับข้อยกเว้นไม่ใช่ข้อผิดพลาดในการคอมไพล์
Drew Noakes

@ BrainSlugs83 อย่างไรก็ตามคุณอาจไม่ต้องการแยกวิเคราะห์ "Infinity" หรือ "NaN" ขึ้นอยู่กับบริบท ดูเหมือนว่าช่องโหว่ที่ดีสำหรับการป้อนข้อมูลของผู้ใช้หากผู้พัฒนาซอฟต์แวร์ไม่เข้มงวดเพียงพอ
ฤดูหนาว

28

จำนวนเต็มตามที่กล่าวถึงคือจำนวนเต็ม พวกเขาไม่สามารถเก็บคะแนนบางอย่างเช่น. 7, .42 และ .007 หากคุณต้องการเก็บตัวเลขที่ไม่ใช่ตัวเลขทั้งหมดคุณต้องการตัวแปรชนิดอื่น คุณสามารถใช้ประเภทคู่หรือประเภทลอย คุณตั้งค่าเหล่านี้ประเภทของตัวแปรขึ้นมาในทางเดียวกันว่า: แทนการใช้คำว่าintคุณพิมพ์หรือdouble floatแบบนี้:

float myFloat;
double myDouble;

( floatสั้นสำหรับ "ทศนิยม" และหมายถึงตัวเลขที่มีบางสิ่งบางอย่างในจุดสิ้นสุด)

ความแตกต่างระหว่างสองคือขนาดของตัวเลขที่พวกเขาสามารถถือ สำหรับfloatคุณสามารถมีตัวเลขได้สูงสุด 7 หลัก สำหรับdoubles คุณสามารถมีได้สูงสุด 16 หลัก เพื่อให้แม่นยำยิ่งขึ้นนี่คือขนาดทางการ:

float:  1.5 × 10^-45  to 3.4 × 10^38  
double: 5.0 × 10^-324 to 1.7 × 10^308

floatเป็นหมายเลข 32 บิตและdoubleเป็นหมายเลข 64 บิต

ดับเบิลคลิกที่ปุ่มใหม่ของคุณเพื่อรับรหัส เพิ่มสามบรรทัดต่อไปนี้ในรหัสปุ่มของคุณ:

double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());

หยุดโปรแกรมของคุณและกลับไปที่หน้าต่างการเข้ารหัส เปลี่ยนบรรทัดนี้:

myDouble = 0.007;
myDouble = 12345678.1234567;

เรียกใช้โปรแกรมของคุณแล้วคลิกปุ่มสองครั้งของคุณ กล่องข้อความแสดงตัวเลขอย่างถูกต้อง เพิ่มหมายเลขอื่นในท้ายที่สุดแล้วและ C # จะปัดขึ้นหรือลงอีกครั้ง คุณธรรมคือถ้าคุณต้องการความแม่นยำระวังการปัดเศษ!


2
"จุดบางสิ่ง" ที่คุณกล่าวถึงโดยทั่วไปจะเรียกว่า "ส่วนที่เป็นเศษส่วน" ของตัวเลข "Floating point" ไม่ได้หมายถึง "ตัวเลขที่มีบางจุดอยู่ท้าย"; แต่แทนที่จะเป็น "Floating Point" แยกประเภทของตัวเลขเมื่อเทียบกับหมายเลข "Fixed Point" (ซึ่งสามารถเก็บค่าเศษส่วนได้) ความแตกต่างคือว่าความแม่นยำได้รับการแก้ไขหรือลอยตัว - ตัวเลขจุดลอยตัวให้ช่วงไดนามิกที่กว้างขึ้นของค่า (ต่ำสุดและสูงสุด) ที่ค่าใช้จ่ายของความแม่นยำในขณะที่ตัวเลขจุดคงที่จะให้ความแม่นยำคงที่ในราคาของช่วง
BrainSlugs83

16
  • ลอย: ± 1.5 x 10 ^ -45 ถึง± 3.4 x 10 ^ 38 (~ 7 ตัวเลขที่สำคัญ
  • double: ± 5.0 x 10 ^ -324 ถึง± 1.7 x 10 ^ 308 (ตัวเลขสำคัญ 15-16 รายการ)
  • ทศนิยม: ± 1.0 x 10 ^ -28 ถึง± 7.9 x 10 ^ 28 (ตัวเลขสำคัญ 28-29)

9
ความแตกต่างเป็นมากกว่าความแม่นยำ - decimalถูกจัดเก็บในรูปแบบทศนิยม (ตรงข้ามกับฐาน 2 ดังนั้นจะไม่สูญเสียหรือปัดเศษตัวเลขเนื่องจากการแปลงระหว่างระบบตัวเลขทั้งสอง) นอกจากนี้decimalไม่มีแนวคิดของค่าพิเศษเช่น NaN, -0, ∞หรือ-∞
BrainSlugs83

13

นี่เป็นหัวข้อที่น่าสนใจสำหรับฉันในวันนี้เราเพิ่งมีข้อผิดพลาดเล็กน้อยที่น่ารังเกียจเกี่ยวกับdecimalการมีความแม่นยำน้อยกว่าfloatการมีความแม่นยำน้อยกว่า

ในรหัส C # ของเราเรากำลังอ่านค่าตัวเลขจากสเปรดชีท Excel แปลงเป็น a decimalแล้วส่งdecimalกลับไปยังบริการเพื่อบันทึกลงในฐานข้อมูลSQL Server

Microsoft.Office.Interop.Excel.Range cell = 
object cellValue = cell.Value2;
if (cellValue != null)
{
    decimal value = 0;
    Decimal.TryParse(cellValue.ToString(), out value);
}

ทีนี้สำหรับค่า Excel ของเราเกือบทั้งหมดแล้วมันก็ใช้ได้ดี แต่สำหรับบางค่า Excel ที่มีขนาดเล็กมากการใช้ค่านั้นdecimal.TryParseหายไปโดยสิ้นเชิง ตัวอย่างหนึ่งคือ

  • cellValue = 0.00006317592

  • Decimal.TryParse (cellValue.ToString (), ค่าออก); // จะคืนค่า0

วิธีแก้ปัญหาที่แปลกประหลาดคือการแปลงค่าของ Excel ให้เป็นdoubleอันดับแรกจากนั้นให้เป็นdecimal:

Microsoft.Office.Interop.Excel.Range cell = 
object cellValue = cell.Value2;
if (cellValue != null)
{
    double valueDouble = 0;
    double.TryParse(cellValue.ToString(), out valueDouble);
    decimal value = (decimal) valueDouble;
    
}

แม้ว่าจะdoubleมีความแม่นยำน้อยกว่า a decimalจริง ๆ แล้วมั่นใจว่าตัวเลขขนาดเล็กจะยังคงรับรู้ ด้วยเหตุผลบางอย่างdouble.TryParseจริง ๆ แล้วสามารถดึงข้อมูลจำนวนน้อยเช่นนั้นในขณะที่decimal.TryParseจะตั้งค่าเป็นศูนย์

แปลก แปลกมาก.


3
จากความอยากรู้สิ่งที่เป็นค่าดิบของ cellValue.ToString ()? Decimal.TryParse ("0.00006317592", val val) ดูเหมือนว่าจะทำงาน ...
micahtan

11
-1 อย่าเข้าใจฉันผิดถ้าเป็นเรื่องจริงมันน่าสนใจมาก แต่นี่เป็นคำถามแยกต่างหากแน่นอนว่าไม่ใช่คำตอบสำหรับคำถามนี้
weston

2
อาจเป็นเพราะเซลล์ Excel ส่งคืนค่า double และ ToString () ค่าคือ "6.31759E-05" ดังนั้น decimal.Parse () จึงไม่ชอบสัญกรณ์ ฉันเดิมพันถ้าคุณตรวจสอบค่าตอบแทนของ Decimal.TryParse () มันจะเป็นเท็จ
SergioL

2
@weston Answers มักเติมเต็มคำตอบอื่น ๆ โดยเติมความแตกต่างที่พวกเขาพลาด คำตอบนี้เน้นความแตกต่างในแง่ของการแยกวิเคราะห์ มันเป็นคำตอบสำหรับคำถามอย่างมาก!
Robino

1
เอ่อ ... ได้decimal.Parse("0.00006317592")ผล - คุณมีอย่างอื่นเกิดขึ้น - สัญกรณ์ทางวิทยาศาสตร์ที่เป็นไปได้?
BrainSlugs83

8

สำหรับแอปพลิเคชั่นเช่นเกมและระบบฝังตัวที่หน่วยความจำและประสิทธิภาพมีความสำคัญอย่างมากโฟลตมักเป็นตัวเลือกประเภทตัวเลขเนื่องจากมันเร็วกว่าและมีขนาดเท่าตัวครึ่งหนึ่ง จำนวนเต็มเคยเป็นอาวุธของตัวเลือก แต่ประสิทธิภาพของจุดลอยมีจำนวนเต็มในโปรเซสเซอร์ที่ทันสมัย ทศนิยมไม่ถูกต้อง!


แทบทุกระบบที่ทันสมัยแม้กระทั่งโทรศัพท์มือถือก็มีการรองรับฮาร์ดแวร์เป็นสองเท่า และถ้าเกมของคุณมีฟิสิกส์ที่เรียบง่ายคุณจะสังเกตเห็นความแตกต่างอย่างมากระหว่าง double และ float (ตัวอย่างเช่นการคำนวณความเร็ว / แรงเสียดทานในการที่ง่ายดาวเคราะห์น้อยโคลนคู่ช่วยให้อัตราเร่งที่จะไหลคล่องตัวมากขึ้นกว่าลอย -. ดูเหมือนว่ามันไม่ควรเรื่อง แต่มันโดยสิ้นเชิงไม่.)
BrainSlugs83

Double Doubles นั้นมีขนาดใหญ่เป็นสองเท่าของลอยซึ่งหมายความว่าคุณต้องเคี้ยวข้อมูลมากขึ้นสองเท่าซึ่งจะทำให้ประสิทธิภาพการทำงานแคชของคุณแย่ลง เช่นเคยวัดและดำเนินการต่อไป
yoyo

6

ชนิดตัวแปรทศนิยมทศนิยมและลอยแตกต่างกันในวิธีการจัดเก็บค่า ความแม่นยำคือความแตกต่างหลักที่ลอยเป็นชนิดข้อมูลจุดลอยตัวความแม่นยำเดียว (32 บิต) double คือชนิดข้อมูลจุดลอยตัวที่มีความแม่นยำสองเท่า (64 บิต) และทศนิยมเป็นชนิดข้อมูลจุดลอยตัว 128 บิต

Float - 32 บิต (7 หลัก)

สอง - 64 บิต (15-16 หลัก)

ทศนิยม - 128 บิต (28-29 หลักสำคัญ)

เพิ่มเติมเกี่ยวกับ ... ความแตกต่างระหว่างทศนิยมลอยและดับเบิล


5

ปัญหาเกี่ยวกับประเภทเหล่านี้ทั้งหมดคือว่ามีบางอย่างไม่แน่ชัดว่ามีอยู่หรือไม่และปัญหานี้อาจเกิดขึ้นกับตัวเลขทศนิยมขนาดเล็กเช่นในตัวอย่างต่อไปนี้

Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1

If fMean - fDelta < fLimit Then
    bLower = True
Else
    bLower = False
End If

คำถาม: ตัวแปร bLower ประกอบด้วยค่าใด?

คำตอบ: บนเครื่อง 32 บิต bLower ประกอบด้วย TRUE !!!

ถ้าฉันแทนที่ Double ด้วย Decimal, bLower มี FALSE ซึ่งเป็นคำตอบที่ดี

สองเท่าปัญหาคือ fMean-fDelta = 1.09999999999 ที่ต่ำกว่า 1.1

ข้อควรระวัง: ฉันคิดว่าปัญหาเดียวกันนี้สามารถเกิดขึ้นได้กับตัวเลขอื่นเนื่องจากทศนิยมเป็นเพียงสองเท่าที่มีความแม่นยำสูงกว่าและความแม่นยำก็มีขีด จำกัด อยู่เสมอ

ในความเป็นจริง Double, Float และ Decimal สอดคล้องกับทศนิยม BINARY ใน COBOL!

เป็นเรื่องน่าเศร้าที่ประเภทตัวเลขอื่น ๆ ที่ใช้ใน COBOL ไม่มีอยู่ใน. Net สำหรับผู้ที่ไม่ทราบภาษาโคบอลมีอยู่ในภาษาโคบอลประเภทต่อไปนี้เป็นตัวเลข

BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte) 

4

ในคำง่าย ๆ :

  1. ชนิดตัวแปรทศนิยมทศนิยมและลอยแตกต่างกันในวิธีการจัดเก็บค่า
  2. ความแม่นยำคือความแตกต่างหลัก (โปรดสังเกตว่านี่ไม่ใช่ความแตกต่างเดียว) โดยที่floatเป็นชนิดข้อมูลจุดลอยตัวที่มีความแม่นยำเดียว (32 บิต) doubleคือความแม่นยำสองเท่า (64 บิต) ชนิดข้อมูลทศนิยมและทศนิยมเป็น 128 บิต ชนิดข้อมูลจุดลอย
  3. ตารางสรุป:

/==========================================================================================
    Type       Bits    Have up to                   Approximate Range 
/==========================================================================================
    float      32      7 digits                     -3.4 × 10 ^ (38)   to +3.4 × 10 ^ (38)
    double     64      15-16 digits                 ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
    decimal    128     28-29 significant digits     ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
คุณสามารถอ่านเพิ่มเติมได้ที่นี่ , ลอย ,คู่และทศนิยม


คำตอบนี้เพิ่มอะไรที่ยังไม่ครอบคลุมในคำตอบที่มีอยู่ BTW, คุณ "หรือ" ในบรรทัด "ทศนิยม" ไม่ถูกต้อง: เครื่องหมายทับในหน้าเว็บที่คุณกำลังคัดลอกจากหมายถึงการหารมากกว่าทางเลือก
Mark Dickinson

1
และฉันจะโต้เถียงอย่างยิ่งว่าความแม่นยำเป็นความแตกต่างหลัก ความแตกต่างที่สำคัญคือฐาน: ทศนิยมทศนิยมกับทศนิยมทศนิยม ความแตกต่างนั่นคือสิ่งที่ทำให้Decimalเหมาะสำหรับการใช้งานทางการเงินและเป็นเกณฑ์หลักในการใช้งานเมื่อตัดสินใจระหว่างและDecimal Doubleมันยากที่Doubleความแม่นยำนั้นไม่เพียงพอสำหรับการใช้งานทางวิทยาศาสตร์เช่น (และDecimalมักจะไม่เหมาะสมสำหรับการใช้งานทางวิทยาศาสตร์เนื่องจากมีช่วง จำกัด )
Mark Dickinson

2

ความแตกต่างที่สำคัญระหว่างกันคือความแม่นยำ

floatคือ32-bitตัวเลขdoubleคือ64-bitตัวเลขและdecimalเป็น128-bitตัวเลข


0
  • ทศนิยม 128 บิต (28-29 หลักสำคัญ) ในกรณีของการใช้งานทางการเงินควรใช้ประเภททศนิยมเพราะให้ความแม่นยำระดับสูงและง่ายต่อการหลีกเลี่ยงข้อผิดพลาดในการปัดเศษใช้ทศนิยมสำหรับคณิตศาสตร์ที่ไม่ใช่จำนวนเต็มที่ต้องการความแม่นยำ (เช่น เงินและสกุลเงิน)

  • Double 64 bit (15-16 หลัก) Double Type เป็นประเภทข้อมูลที่ใช้งานมากที่สุดสำหรับค่าจริงยกเว้นการจัดการเงิน ใช้สองเท่าสำหรับคณิตศาสตร์ที่ไม่ใช่จำนวนเต็มซึ่งไม่จำเป็นต้องใช้คำตอบที่แม่นยำที่สุด

  • Float 32 บิต (7 หลัก) ส่วนใหญ่จะใช้ในไลบรารีกราฟิกเพราะความต้องการพลังการประมวลผลสูงมากรวมทั้งใช้สถานการณ์ที่สามารถทนต่อข้อผิดพลาดในการปัดเศษ

Decimalsช้ากว่าdouble/floatมาก

DecimalsและFloats/Doublesไม่สามารถเปรียบเทียบได้โดยไม่ต้องใช้นักแสดงในขณะที่FloatsและDoublesสามารถ

Decimals อนุญาตการเข้ารหัสหรือต่อท้ายเลขศูนย์


-1

เพื่อกำหนดทศนิยมทศนิยมและคู่ใน. Net (c #)

คุณต้องพูดถึงค่าเป็น:

Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;

และตรวจสอบผลลัพธ์

และไบต์ที่ถูกครอบครองโดยแต่ละคนนั้น

Float - 4
Double - 8
Decimal - 12
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.