ดูเหมือนว่าคุณจะเห็นประโยชน์ของการใช้ชนิดจุดลอยตัว ฉันมักจะออกแบบสำหรับทศนิยมในทุกกรณีและพึ่งพา profiler เพื่อแจ้งให้เราทราบหากการดำเนินการกับทศนิยมนั้นทำให้เกิดปัญหาคอขวดหรือช้าลง ในกรณีเหล่านั้นฉันจะ "ลดระดับลง" เป็นสองเท่าหรือลอย แต่จะทำภายในเท่านั้นและพยายามจัดการการสูญเสียที่แม่นยำด้วยความระมัดระวังโดย จำกัด จำนวนตัวเลขที่สำคัญในการดำเนินการทางคณิตศาสตร์
โดยทั่วไปหากค่าของคุณเป็นแบบชั่วคราว (ไม่ได้นำมาใช้ซ้ำ) คุณจะปลอดภัยในการใช้ชนิดจุดลอย ปัญหาที่แท้จริงของประเภทจุดลอยตัวเป็นสามสถานการณ์
- คุณกำลังรวมค่าจุดลอยตัว (ซึ่งในกรณีนี้คือสารประกอบข้อผิดพลาดความแม่นยำ)
- คุณสร้างค่าตามค่าของจุดลอยตัว (ตัวอย่างเช่นในอัลกอริทึมแบบเรียกซ้ำ)
- คุณกำลังทำคณิตศาสตร์ด้วยตัวเลขจำนวนมาก (ตัวอย่างเช่น
123456789.1 * .000000000000000987654321
)
แก้ไข
ตามเอกสารอ้างอิงใน C # ทศนิยม :
ทศนิยมคำหลักหมายถึง 128 บิตชนิดข้อมูล เมื่อเปรียบเทียบกับทศนิยมประเภททศนิยมมีความแม่นยำมากขึ้นและช่วงที่เล็กลงซึ่งเหมาะสำหรับการคำนวณทางการเงินและการเงิน
ดังนั้นเพื่อชี้แจงงบข้างต้นของฉัน:
ฉันมักจะออกแบบสำหรับทศนิยมในทุกกรณีและพึ่งพา profiler เพื่อแจ้งให้เราทราบหากการดำเนินการกับทศนิยมนั้นทำให้เกิดปัญหาคอขวดหรือช้าลง
ฉันเคยทำงานในอุตสาหกรรมที่มีตำแหน่งเป็นทศนิยม หากคุณกำลังทำงานกับ phsyics หรือเอ็นจิ้นกราฟิกมันน่าจะมีประโยชน์มากกว่าสำหรับการออกแบบสำหรับประเภทจุดลอยตัว (float หรือ double)
ทศนิยมไม่แม่นยำอย่างแน่นอน (เป็นไปไม่ได้ที่จะแสดงความแม่นยำไม่สิ้นสุดสำหรับการไม่รวมในประเภทข้อมูลดั้งเดิม) แต่มันแม่นยำกว่าสองเท่า:
- ทศนิยม = 28-29 ตัวเลขที่สำคัญ
- double = 15-16 เลขนัยสำคัญ
- float = 7 ตัวเลขนัยสำคัญ
แก้ไข 2
เพื่อตอบสนองต่อความคิดเห็นของKonrad Rudolphรายการ # 1 (ด้านบน) นั้นถูกต้องแน่นอน การรวมกันของความไม่แน่นอนจะรวมกันแน่นอน ดูรหัสด้านล่างสำหรับตัวอย่าง:
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
ผลลัพธ์นี้ต่อไปนี้:
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
อย่างที่คุณเห็นแม้ว่าเราจะเพิ่มจากค่าคงที่ของแหล่งเดียวกันผลลัพธ์ของ double นั้นมีความแม่นยำน้อยกว่า (แม้ว่าอาจจะเป็นรอบที่ถูกต้อง) และการลอยนั้นมีความแม่นยำน้อยกว่าจนถึงจุดที่ลดลงเหลือเพียง ตัวเลขสองหลักที่สำคัญ