Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f43964b

Browse files
committed
Refactor number formatting and rounding in article.md
1 parent 27397dc commit f43964b

File tree

1 file changed

+146
-1
lines changed

1 file changed

+146
-1
lines changed

‎1-js/05-data-types/02-number/article.md‎

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,149 @@ alert( num.toString(2) ); // 11111111
157157

158158
1. คูณและหาร
159159

160-
เช่น เพื่อปัดเศษตัวเลขไปยังตําแหน่งทศนิยมที่ 2 เราสามารถคูณตัวเลขด้วย `100` (หรือกําลังของ 10 ที่มากกว่า) เรียกใช้ฟังก์ชันป
160+
เช่น เพื่อปัดเศษตัวเลขไปยังตําแหน่งทศนิยมที่ 2 เราสามารถคูณตัวเลขด้วย `100` (หรือกําลังของ 10 ที่มากกว่า) เรียกใช้ฟังก์ชันปัดเศษ แล้วหารกลับ
161+
```js run
162+
let num = 1.23456;
163+
164+
alert( Math.round(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23
165+
```
166+
167+
2. วิธี [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) ปัดเศษตัวเลขไปยัง `n` ตําแหน่งหลังจุดทศนิยมและคืนค่าเป็นสตริง
168+
169+
```js run
170+
let num = 12.34;
171+
alert( num.toFixed(1) ); // "12.3"
172+
```
173+
174+
วิธีนี้ปัดขึ้นหรือลงไปยังค่าที่ใกล้ที่สุด คล้ายกับ `Math.round`:
175+
176+
```js run
177+
let num = 12.36;
178+
alert( num.toFixed(1) ); // "12.4"
179+
```
180+
181+
โปรดทราบว่าผลลัพธ์ของ `toFixed` เป็นสตริง หากส่วนทศนิยมสั้นกว่าที่ต้องการ จะเพิ่มศูนย์ต่อท้าย:
182+
183+
```js run
184+
let num = 12.34;
185+
alert( num.toFixed(5) ); // "12.34000", เพิ่มศูนย์เพื่อให้ครบ 5 หลัก
186+
```
187+
188+
เราสามารถแปลงเป็นตัวเลขโดยใช้เครื่องหมายบวกเดี่ยวหรือเรียก `Number()`: `+num.toFixed(5)`
189+
190+
## การคํานวณที่ไม่แม่นยํา
191+
192+
ภายใน ตัวเลขถูกเก็บในรูปแบบ 64 บิต [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision) มีบิต 64 บิตเพื่อเก็บตัวเลข: 52 บิตใช้เก็บตัวเลข, 11 บิตเก็บตําแหน่งของจุดทศนิยม (เป็นศูนย์สําหรับจํานวนเต็ม) และ 1 บิตสําหรับเครื่องหมาย
193+
194+
ถ้าตัวเลขใหญ่เกินไป อาจล้นพื้นที่เก็บข้อมูล 64 บิต ทําให้ได้ค่าอนันต์:
195+
196+
```js run
197+
alert( 1e500 ); // Infinity
198+
```
199+
200+
สิ่งที่อาจไม่ชัดเจนนัก แต่เกิดขึ้นบ่อย คือการสูญเสียความแม่นยํา
201+
202+
พิจารณาการทดสอบนี้ (ที่ให้ผลเป็นเท็จ):
203+
204+
```js run
205+
alert( 0.1 + 0.2 == 0.3 ); // เท็จ
206+
```
207+
208+
ถูกต้อง ถ้าเราตรวจสอบว่าผลรวมของ `0.1` และ `0.2` เท่ากับ `0.3` เราจะได้ `เท็จ`
209+
210+
แปลก! แล้วมันคืออะไรถ้าไม่ใช่ `0.3`?
211+
212+
```js run
213+
alert( 0.1 + 0.2 ); // 0.30000000000000004
214+
```
215+
216+
โอ้! มีผลกระทบมากกว่าการเปรียบเทียบที่ไม่ถูกต้อง ลองนึกภาพว่าคุณกําลังทําเว็บไซต์ขายของออนไลน์ และลูกค้าใส่สินค้ามูลค่า `0ドル.10` และ `0ドル.20` ลงในตะกร้า ยอดรวมจะเป็น `0ドル.30000000000000004` ซึ่งจะทําให้ทุกคนแปลกใจ
217+
218+
แต่ทําไมถึงเกิดเรื่องนี้ขึ้น?
219+
220+
ตัวเลขถูกเก็บในหน่วยความจําในรูปแบบไบนารี เป็นลําดับของบิต 0 และ 1 แต่เศษส่วนเช่น `0.1`, `0.2` ที่ดูง่ายในระบบเลขฐานสิบ จริงๆ แล้วเป็นเศษส่วนไม่รู้จบในระบบไบนารี
221+
222+
กล่าวคือ `0.1` คืออะไร? มันคือ 1 หาร 10 หรือ `1/10` ในระบบเลขฐานสิบ ตัวเลขแบบนี้แสดงได้ง่าย เปรียบเทียบกับ 1 หาร 3 หรือ `1/3` ซึ่งเป็นเศษส่วนไม่รู้จบ `0.33333(3)`
223+
224+
ดังนั้น การหารด้วยกําลังของ 10 รับประกันว่าจะทํางานได้ดีในระบบฐานสิบ แต่การหารด้วย 3 ไม่ใช่ ด้วยเหตุผลเดียวกัน ในระบบไบนารี การหารด้วยกําลังของ 2 รับประกันว่าจะทํางานได้ แต่ `1/10` กลายเป็นเศษส่วนไบนารีไม่รู้จบ
225+
226+
ไม่มีทางเก็บ *0.1 หรือ 0.2 อย่างแม่นยํา* โดยใช้ระบบไบนารี เช่นเดียวกับที่ไม่มีทางเก็บหนึ่งส่วนสามเป็นเศษส่วนทศนิยมได้อย่างแม่นยํา
227+
228+
รูปแบบตัวเลข IEEE-754 แก้ปัญหานี้โดยปัดเศษไปยังตัวเลขที่ใกล้ที่สุดที่เป็นไปได้ กฎการปัดเศษเหล่านี้ปกติไม่ให้เราเห็น "การสูญเสียความแม่นยําเล็กน้อย" นั้น แต่มันมีอยู่
229+
230+
เราสามารถเห็นสิ่งนี้ในการทํางาน:
231+
```js run
232+
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
233+
```
234+
235+
และเมื่อเรารวมสองตัวเลข "การสูญเสียความแม่นยํา" ของพวกมันจะรวมกัน
236+
237+
นั่นคือเหตุผลที่ `0.1 + 0.2` ไม่เท่ากับ `0.3` อย่างแม่นยํา
238+
239+
```smart header="ไม่ใช่แค่จาวาสคริปต์"
240+
ปัญหาเดียวกันนี้มีอยู่ในภาษาโปรแกรมอื่นๆ หลายภาษา
241+
242+
PHP, Java, C, Perl, Ruby ให้ผลลัพธ์เดียวกัน เพราะพวกมันใช้รูปแบบตัวเลขเดียวกัน
243+
```
244+
245+
เราสามารถแก้ไขปัญหานี้ได้ไหม? แน่นอน วิธีที่น่าเชื่อถือที่สุดคือปัดเศษผลลัพธ์โดยใช้วิธี [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed):
246+
247+
```js run
248+
let sum = 0.1 + 0.2;
249+
alert( sum.toFixed(2) ); // 0.30
250+
```
251+
252+
โปรดทราบว่า `toFixed` คืนค่าเป็นสตริงเสมอ มันรับประกันว่าจะมี 2 ตําแหน่งหลังจุดทศนิยม ซึ่งสะดวกถ้าเรามีร้านค้าออนไลน์และต้องแสดง `0ドル.30` สําหรับกรณีอื่นๆ เราสามารถใช้เครื่องหมายบวกเดี่ยวเพื่อแปลงเป็นตัวเลข:
253+
254+
```js run
255+
let sum = 0.1 + 0.2;
256+
alert( +sum.toFixed(2) ); // 0.3
257+
```
258+
259+
เราสามารถคูณตัวเลขด้วย 100 (หรือตัวเลขที่ใหญ่กว่า) ชั่วคราวเพื่อเปลี่ยนให้เป็นจํานวนเต็ม ทําการคํานวณ แล้วหารกลับ เมื่อทําเช่นนี้ ข้อผิดพลาดจะลดลงบ้าง แต่ยังคงมีเมื่อหาร:
260+
261+
```js run
262+
alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
263+
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001
264+
```
265+
266+
ดังนั้น วิธีคูณ/หารช่วยลดข้อผิดพลาด แต่ไม่ได้กําจัดออกทั้งหมด
267+
268+
บางครั้งเราอาจพยายามหลีกเลี่ยงเศษส่วนทั้งหมด เช่น ถ้าเราทําเรื่องร้านค้า เราอาจเก็บราคาเป็นเซนต์แทนดอลลาร์ แต่ถ้าเราลดราคา 30% ล่ะ? ในทางปฏิบัติ การหลีกเลี่ยงเศษส่วนทั้งหมดแทบจะเป็นไปไม่ได้ เพียงแค่ปัดเศษตัดทศนิยมเมื่อจําเป็น
269+
270+
````smart header="เรื่องแปลก"
271+
ลองรันโค้ดนี้ดู:
272+
273+
```js run
274+
// สวัสดี! ฉันเป็นตัวเลขที่เพิ่มขึ้นเอง!
275+
alert( 9999999999999999 ); // แสดง 10000000000000000
276+
```
277+
278+
นี่เกิดจากปัญหาเดียวกัน: การสูญเสียความแม่นยํา มี 64 บิตสําหรับตัวเลข, 52 บิตใช้เก็บตัวเลข แต่ไม่พอ ดังนั้นตัวเลขที่มีนัยสําคัญน้อยที่สุดจึงหายไป
279+
280+
จาวาสคริปต์ไม่แจ้งข้อผิดพลาดในกรณีเช่นนี้ มันพยายามทําให้ตัวเลขพอดีกับรูปแบบที่ต้องการ แต่น่าเสียดายที่รูปแบบนี้ไม่ใหญ่พอ
281+
````
282+
283+
```smart header="สองศูนย์"
284+
ผลพลอยได้ที่แปลกอีกอย่างของการแสดงตัวเลขภายในคือการมีศูนย์สองแบบ: `0` และ `-0`
285+
286+
นั่นเพราะเครื่องหมายถูกแสดงด้วยบิตเดียว ดังนั้นจึงอาจตั้งค่าหรือไม่ตั้งค่าสําหรับตัวเลขใดๆ รวมถึงศูนย์
287+
288+
ในกรณีส่วนใหญ่ ความแตกต่างไม่สังเกตเห็น เพราะตัวดําเนินการปฏิบัติต่อพวกมันเหมือนกัน
289+
```
290+
291+
## การทดสอบ: isFinite และ isNaN
292+
293+
จําค่าตัวเลขพิเศษสองค่านี้ได้ไหม?
294+
295+
- `Infinity` (และ `-Infinity`) เป็นค่าตัวเลขพิเศษที่มากกว่า (น้อยกว่า) ทุกอย่าง
296+
- `NaN` แทนข้อผิดพลาด
297+
298+
ค่าเหล่านี้เป็นประเภท `number` แต่ไม่ใช่ตัวเลข "ปกติ" จึงมีฟังก์ชันพิเศษสําหรับตรวจสอบ:
299+
300+
301+
- `isNaN(value)` แปลงอาร์กิวเมนต์เป็นตัวเลขแล้วทดสอบว่าเป็น `NaN`:
302+
303+
```js run
304+
alert( isNaN(NaN) ); // จริง
305+
alert( isNaN("str") ); // จริง

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /