หนึ่งในปัญหาคลาสิก เวลาเขียนโปรแกรมที่ทุกคนต้องเจอเลย
ก็คือการบวกลบเลขทศนิยมในภาษาโปรแกรม ของบางภาษา นี้แหละ
เช่น JavaScript, Python, Perl, C#, C, C++, Java, PHP, Fortran
(และอื่นๆ อีกหลายภาษาที่ไม่ได้กล่าวถึง)
.
หลายครั้งที่มันอาจเพี้ยนได้ เช่น
👉 0.1+0.2 ไม่ได้เท่ากับ 0.3
แต่ได้เป็น 0.30000000000000004
.
👉 หรือ 0.1 บวกกัน 10 ครั้ง ก็ไม่ได้เป็น 1
แต่ได้เป็น 0.9999999999999999
.
คนเขียนโปรแกรมเจอแบบนี้เข้าไป
ก็เหมือนมวยโดนหมัดน๊อคมึนงงในดงโค้ด
:
:
แต่ใช่ว่ามันจะเพี้ยนทุกครั้ง ซะเมื่อไร เช่น
0.5+0.5 = 1 (ถูกต้องเป๊ะ)
0.2+0.3 = 0.5 (บังเอิญไม่เพี้ยน)
.
สำหรับ กรณี 0.2 กับ 0.3 มันถูกตัดเศษเหลือเป็น
0.2000000000000000111022302462515654042363166809082031250
กับ
0.2999999999999999888977697537484345957636833190917968750
พอบวกกันจึงได้ 0.5 พอดี แบบฟลุ๊คๆๆ ซึ่งไม่ควรทำได้
(ตรงสอบดูได้ 0.2+0.3 == 0.5 ได้ค่าออกมาเป็น true)
:
:
สาเหตุที่เป็นเช่นนี้
ก็เพราะว่าคอมพิวเตอร์มันรู้จักแต่ เลขฐาน2 อะนะ
ต่อให้เราเขียนโค้ดใช้เลขฐาน10 ก็ตาม
สุดท้ายเวลาโค้ดมันถูกรัน ก็จะกลายเป็นเลขฐาน 2 อยู่ดี
.
😨 แล้วก็เป็นความซวยที่จะมาเยือนคนเขียนโปรแกรม
เพราะเวลาแปลงเลขฐาน10 ไปเป็นเลขฐาน 2
บางกรณีมันแปลงแล้ว ดันได้ตัวเลขที่ไม่รู้จบเสียด้วยซิ
จึงทำให้การเก็บทศนิยมผิดเพี้ยนไปได้
.
สำหรับรูปแบบการจัดเก็บเลขทศนิยม ในหลายภาษา
เขาจะนิยมใช้มาตรฐาน IEEE-754 floating point
เช่น 0.1 จะถูกมองว่าคือ 1/10
.
เมื่อเก็บเป็นเลขทศนิยมฐานสอง
ตามมาตรฐาน IEEE-754 floating point จะได้เป็น
0.0001100110011001100110011001100110011001100110011...
เป็นทศนิยมไม่รู้จบในรูปเลขฐานสอง ....นี้คือสิ่งที่คอมมองเห็น
.
พอคอมแปลงกลับมาเป็นทศนิยม เพื่อให้มนุษย์โลกอ่านเข้าใจ
ในรูปฐาน 10 ก็จะได้เป็น
0.1000000000000000055511151231257827021181583404541015625
ทว่าคอมมันจะตัดให้เหลือแค่ 0.1 (คนจึงเห็นแค่นี้)
:
🤔 ซึ่งความเพื้ยนแบบนี้
แน่นอนทำให้เกิดบั๊กเวลาคำนวณตัวเลข
- ยิ่งงานต้องการคำตอบที่ละเอียดมาก เช่น งานธนาคาร ก็จะประสบปัญหา เป็นต้น
- หรือเวลานำไปใช้ในเงื่อนไขเปรียบเทียบพวก if, while ฯลฯ ก็อาจมีบั๊กเกิดขึ้นได้ เป็นต้น
.
😀 แต่ไม่ต้องห่วง ในหลายๆ ภาษาเขาจะมีวิธีแก้ปัญหานี้อยู่ครับ
ป้องกันการคำนวณตัวเลข ไม่ให้คลาดเคลื่อน เช่น
- ใน Java ก็จะมีคลาส BigDecimal เอาไว้บวกลบคูณหาร สำหรับเลขทศนิยมโดยเฉพาะ
- ใน Python ก็จะมีคลาสคล้ายๆ กัน เช่น Decimal
- ส่วนใน JavaScript อาจใช้ไลบรารี่ ซึ่งมีให้เลือกเยอะเช่น
https://github.com/MikeMcl/decimal.js/
https://github.com/MikeMcl/bignumber.js/
https://github.com/MikeMcl/big.js/
- ภาษาอื่นที่เหลือลองไปศึกษาเองดูนะครับ
.
.
เรื่องบวกลบคูณหาร เลขทศนิยม ถือเป็นเรื่องสำคัญที่ไม่ควรมองข้าม
โดยส่วนตัวก็เคยเจอความเผลอเรอตรงนี้
ในระดับโปรเจคระดับธนาคาร ก็เคยพลาดมาแล้ว
สุดท้ายต้องมาไล่นั่งแก้โค้ดหลายบรรทัด
เสียเวลานั่งไล่ test ใหม่อีกรอบอีก
.
หมายเหตุเห็นคอมเมนต์สงสัยว่า
PHP กับ C# รอดชะตากรรมเดียวกันไหม ?
ก็บอกว่าไม่รอดครับ
.
// ลองดูตัวอย่างโค้ด C#
Console.WriteLine( ((0.1+0.2) == 0.3)); // False
Console.WriteLine( ((0.1+0.2) == 0.30000000000000004)); // True
// ลองดูตัวอย่างโค้ด PHP
echo number_format(0.1+0.2 , 17);
.
++++++
เขียนโดย โปรแกรมเมอร์ไทย thai programmer
อ่านเรื่อง IEEE-754 floating point ได้ที่
https://th.wikipedia.org/wiki/จำนวนจุดลอยตัว
One of those classic problems, programming that everyone needs to encounter.
It's positive to delete decimal numbers in some language.
เช่น JavaScript, Python, Perl, C#, C, C++, Java, PHP, Fortran
(and many other languages not mentioned)
.
Many times it can be crazy like
👉 0.1 + 0.2 is not equal to 0.3
But I got to be 0.30000000000000004
.
👉 or 0.1 plus 10 times. It's not 1
But I got to be 0.9999999999999999
.
The Programmer found this.
It's like boxing. I got hit by a punch. I'm confused in dong code.
:
:
But it's not that it's crazy every time like
0.5 + 0.5 = 1 (exactly correct)
0.2 + 0.3 = 0.5 (accidentally not crazy)
.
For Case 0.2 and 0.3 it was cut down.
0.2000000000000000111022302462515654042363166809082031250
With the.
0.2999999999999999888977697537484345957636833190917968750
When we are positive, we get 0.5 fit like fluke which you shouldn't be able to do.
(I can watch the exam. 0.2 + 0.3 == 0.5 get the value to be true)
:
:
The cause is like this
Because computers only know the base number 2
Even if we write code, use base number 10
In the end, when the code is run, it will become base number 2 anyway.
.
😨 and it's bad luck to visit the programmer.
Because time to convert base number 10 to base number 2
In some cases, it's converted and I get the number that I don't end.
So it makes the decimal picking wrong.
.
For the decimal number storage in multiple languages
He will be popular with IEEE-754 floating point standards
For example, 0.1 will be seen as 1/10
.
When keeping it as a decimal number, base two.
According to IEEE-754 floating point standards.
0.0001100110011001100110011001100110011001100110011...
It's a decimal. I don't finish in the second base picture.... this is what the computer can see.
.
When the computer converts back to decimal so that the world can read and understand.
In the picture of base 10 will be.
0.1000000000000000055511151231257827021181583404541015625
But the computer will cut to only 0.1 (so people see this)
:
🤔 this kind of being
Sure. It makes cuddle times to calculate numbers.
- the more jobs need detailed answers such as banking work, there will be problems, etc.
- or time to use in comparison terms. If, while etc. There may be cuddle baht.
.
😀 but don't worry. in many languages, there will be a solution to this problem.
Prevent calculation of numbers from inaccurate such as
- in Java, there will be bigdecimal class to delete multiplication for decimal numbers especially.
- in python, there will be similar classes such as decimal.
- Javascript may use a lot of libraries to choose from.
https://github.com/MikeMcl/decimal.js/
https://github.com/MikeMcl/bignumber.js/
https://github.com/MikeMcl/big.js/
- the rest of the other languages, try to study it yourself.
.
.
It's important to delete multiplication, divide the decimal numbers. It's important that you should not overlook.
Personally, I have met a burp here.
At Project Level, bank level has been missed.
Finally, I have to sit and fix many lines of code.
Wasting time to sit and chase the test again.
.
Note that I see the comments. I wonder if
Php and c #survive the same fate?
I said I wouldn't survive.
.
// check out the code C Sample #
Console.WriteLine( ((0.1+0.2) == 0.3)); // False
Console.WriteLine( ((0.1+0.2) == 0.30000000000000004)); // True
// check out the sample code php
echo number_format(0.1+0.2 , 17);
.
++++++
Written by Thai Programmer Thai programmer
Read about IEEE-754 floating point at
https://th.wikipedia.org/wiki/จำนวนจุดลอยตัวTranslated
同時也有10000部Youtube影片,追蹤數超過2,910的網紅コバにゃんチャンネル,也在其Youtube影片中提到,...
「bigdecimal divide」的推薦目錄:
- 關於bigdecimal divide 在 โปรแกรมเมอร์ไทย Thai programmer Facebook 的精選貼文
- 關於bigdecimal divide 在 コバにゃんチャンネル Youtube 的最佳貼文
- 關於bigdecimal divide 在 大象中醫 Youtube 的最佳貼文
- 關於bigdecimal divide 在 大象中醫 Youtube 的精選貼文
- 關於bigdecimal divide 在 java - How can I divide properly using BigDecimal 的評價
- 關於bigdecimal divide 在 QueryDSL Collection util for BigDecimal divide Expression 的評價
- 關於bigdecimal divide 在 Java BigDecimal - YouTube 的評價
- 關於bigdecimal divide 在 Java BigDecimal Tutorial - 1 - YouTube 的評價
- 關於bigdecimal divide 在 bignumber.js API 的評價
bigdecimal divide 在 コバにゃんチャンネル Youtube 的最佳貼文
bigdecimal divide 在 大象中醫 Youtube 的最佳貼文
bigdecimal divide 在 大象中醫 Youtube 的精選貼文
bigdecimal divide 在 QueryDSL Collection util for BigDecimal divide Expression 的推薦與評價
public static NumberExpression<BigDecimal> divide(final BigDecimal dividend, final BigDecimal divisor, final int scale, final RoundingMode roundingMode) {. ... <看更多>
bigdecimal divide 在 Java BigDecimal - YouTube 的推薦與評價
... BigDecimal in Java. Creating a BigDecimal from String, compare BigDecimal objects, add/subtract BigDecimals, BigDecimal division. Round and ... ... <看更多>
bigdecimal divide 在 java - How can I divide properly using BigDecimal 的推薦與評價
... <看更多>