บล็อก

Boring Expenses เก็บจำนวนเงินอย่างไร (และทำไมเป็นจำนวนเต็ม)

  • วิศวกรรม
  • iOS
  • Swift

มีวิธีคลาสสิกที่ทำให้เงินหายไปหนึ่งสตางค์ ลองถามภาษาโปรแกรมเกือบทุกภาษาว่า 0.1 + 0.2 เท่ากับเท่าไร มันจะตอบว่า 0.30000000000000004 นี่ไม่ใช่บั๊กของภาษา แต่เป็นธรรมชาติของเลขทศนิยมลอยตัวแบบไบนารี มันแทนเศษส่วนทศนิยมส่วนใหญ่ได้ไม่ตรงเป๊ะ ความคลาดเคลื่อนเล็กๆ จึงแทรกเข้ามา ใช้กับฟิสิกส์ได้ แต่ใช้กับเงินไม่ได้

สำหรับแอปการเงิน “ประมาณถูก” คือคำตอบที่ผิด Boring Expenses จึงไม่เคยเก็บจำนวนเงินเป็นเลขทศนิยม

เก็บหน่วยที่เล็กที่สุดเป็นจำนวนเต็ม

เคล็ดลับที่ซอฟต์แวร์การเงินใช้มานานคือคำนวณด้วยหน่วยที่เล็กที่สุดและเก็บเป็นจำนวนเต็ม แทนที่จะเก็บ ฿4.20 ก็เก็บเป็น 420 คือจำนวนสตางค์ จำนวนเต็มแม่นยำเสมอ จะบวก ลบ รวมยอดทั้งวัน ก็ไม่มีฝุ่นจากการปัดเศษสะสม

Boring Expenses ไปไกลกว่านั้นอีกขั้น โดยเก็บจำนวนเงินเป็นหน่วยย่อยที่ละเอียดมาก (ลองนึกถึง “100 ล้านต่อหนึ่งหน่วย”) ซึ่งเหลือพื้นที่ให้สกุลเงินต่างๆ และความต้องการในอนาคตอย่างเหลือเฟือ ขณะที่ทุกอย่างยังเป็น Int ธรรมดา การแปลงเป็นตัวเลขที่เห็นบนหน้าจอเกิดขึ้นแค่ที่ขอบเท่านั้น คือตอนคุณพิมพ์จำนวนเงิน และตอนเราจัดรูปแบบเพื่อแสดงผล

// ตัวอย่างประกอบ ไม่ใช่โค้ดจริง:
let display = Decimal(amountInSubunits) / Decimal(subunitsPerUnit)
let text = display.formatted(.currency(code: userCurrency))

ทำไมเรื่องนี้สำคัญกับคุณ

เป็นการตัดสินใจเล็กๆ ที่ไม่หวือหวา ตรงกับแบบที่เราชอบ คุณจะไม่มีวันเห็นมัน และนั่นคือประเด็น ตัวเลขแค่ลงตัว