dimesum

หน้าแรก / บล็อก / เงิน

เงิน

วิธีแบ่งบิลเมื่อมีจานที่ไม่ได้แชร์กัน

· อ่าน 6 นาที ·

แบ่งค่าอาหาร ฿525 เท่ากันแล้วมีคนจ่าย ฿70 สำหรับจานที่ไม่ได้กิน วิธีแก้คือค่าใช้จ่ายเดียวกับสองกฎ: ระบุคนที่กินรายการที่ไม่ได้แชร์ และให้ภาษีเป็นไปตามการบริโภค

แบ่งค่าอาหารมื้อละ ฿525 เท่ากันทุกคน แล้วมีคนหนึ่งจ่ายเกินไป ฿70 สองในสามคนกินจานซีฟู้ดราคา ฿200 ส่วนคนที่สามไม่ได้กิน แต่การหารเท่ากันกลับคิดเงินทั้งสามคนคนละ ฿175 Dimesum จัดการบิลนี้เป็นค่าใช้จ่ายรายการเดียว: หารเท่ากันในระดับบน โดยให้รายการ ฿200 ตกอยู่กับสองคนที่สั่งมันเท่านั้น

บิลที่หารเท่ากันเป็นส่วนใหญ่โดยมีรายการหนึ่งที่ไม่ได้แชร์กัน คือสิ่งที่แอปแบ่งบิลถูกขอให้ทำบ่อยที่สุด และโมเดลข้อมูลแรกของ Dimesum ไม่สามารถแสดงมันได้ การออกแบบก่อนหน้านี้ทำให้ ITEMIZED เป็นชนิดของการแบ่ง ซึ่งใช้ร่วมกับ EQUAL PERCENT และ SHARES ไม่ได้ แต่บิลร้านอาหารจริงเป็นทั้งสองอย่างพร้อมกัน

การแยกรายการเป็นรายละเอียดของค่าใช้จ่าย ไม่ใช่การแบ่งอีกชนิดหนึ่ง

ค่าใช้จ่ายแบบแยกรายการใน Dimesum คือค่าใช้จ่ายธรรมดาที่บังเอิญมีรายการต่างๆ ของมัน ค่าใช้จ่ายนี้ยังคงมีทุกอย่างที่ค่าใช้จ่ายมีอยู่แล้ว: ยอดรวม ผู้ร่วมจ่าย ชนิดของการแบ่ง และผู้จ่ายหนึ่งคนหรือหลายคน นอกจากนั้นมันเพิ่มรายการสินค้า ซึ่งเป็นบรรทัดต่างๆ ของบิล และการปรับ ได้แก่ ภาษี ทิป ค่าธรรมเนียม และส่วนลด ที่พิมพ์อยู่ใต้รายการเหล่านั้น

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

สองระดับที่กำหนดการแบ่งของบรรทัด จาก docs/tech/18-itemized-expenses.md §1.
ระดับกำหนดอะไรใช้กับ
ชนิดการแบ่งของค่าใช้จ่ายวิธีที่ต้นทุนที่แชร์กันถูกหาร: เท่ากัน ตามเปอร์เซ็นต์ หรือตามสัดส่วนที่ถ่วงน้ำหนักทุกรายการที่ไม่มีการระบุผู้ถูกกำหนด
ผู้ถูกกำหนดของรายการใครบริโภคบรรทัดนี้ และในสัดส่วนเท่าใดเฉพาะบรรทัดนั้น
บรรทัดที่ไม่มีผู้ถูกกำหนดจะหารตามชนิดการแบ่งของค่าใช้จ่าย ส่วนบรรทัดที่มีผู้ถูกกำหนดจะตกอยู่กับเฉพาะคนที่มันระบุชื่อเท่านั้น ระดับ 1: ไม่มีการระบุชื่อใครบนบรรทัด จานที่แชร์กัน ฿300 ไม่มีผู้ถูกกำหนด EQUAL หาร 3 Asha ฿100 Bhavna ฿100 Chetan ฿100 ระดับ 2: บรรทัดระบุว่าใครกินมัน จานที่ไม่ใช่มังสวิรัติ ฿200 ผู้ถูกกำหนด: Asha, Bhavna ผู้ถูกกำหนด 2 คนของมัน Asha ฿100 Bhavna ฿100 Chetan ฿0
สองระดับบนค่าอาหาร ฿500 จานที่แชร์กันไม่ระบุชื่อใคร ดังนั้น EQUAL จึงหารมันเป็นสามส่วน ส่วนจานซีฟู้ดระบุชื่อสองคน ดังนั้นยอดค่าอาหารย่อยของ Chetan จึงหยุดอยู่ที่ ฿100

มื้ออาหาร ฿525 ที่คนที่กินน้อยที่สุดจ่าย ฿105

Asha, Bhavna และ Chetan กินอาหารเย็น โดยหารเท่ากันในระดับบน จานที่แชร์กันรวมเป็น ฿300 จานซีฟู้ดรวมเป็น ฿200 และมีเพียง Asha กับ Bhavna ที่กินมัน ค่าบริการ 5% และ Chetan เป็นคนจ่ายทั้งหมด ฿525

ตัวอย่างการคำนวณ: หนึ่งบิล สองบรรทัด หนึ่งการปรับ และส่วนที่แต่ละคนต้องรับ
บรรทัดจำนวนAshaBhavnaChetan
จานที่แชร์กัน ไม่มีผู้ถูกกำหนด฿300฿100฿100฿100
จานซีฟู้ด Asha และ Bhavna฿200฿100฿100฿0
ยอดย่อย฿500฿200฿200฿100
ค่าบริการ 5% ตามยอดย่อย฿25฿10฿10฿5
ยอดรวม฿525฿210฿210฿105

Chetan จ่าย ฿525 และค้างอยู่ ฿105 ดังนั้นเขาควรได้รับคืน ฿420: ฿210 จาก Asha และ ฿210 จาก Bhavna ใครเป็นคนจ่ายเป็นเรื่องที่แยกจากใครเป็นคนค้าง การที่ผู้จ่ายเป็นคนที่แทบไม่ได้กินเลยไม่เปลี่ยนส่วนแบ่งใดๆ ซึ่งเป็นเหตุผลที่ Dimesum เก็บผู้จ่ายไว้ที่ระดับค่าใช้จ่าย และเก็บผู้ถูกกำหนดไว้ที่ระดับบรรทัด

ภาษีเป็นไปตามสิ่งที่คุณกิน ไม่ใช่ตามจำนวนคน

ส่วนของ Chetan ในค่าบริการ ฿25 คือ ฿5 ไม่ใช่ ฿8.33 ทุกการปรับถูกจัดสรรตามสัดส่วนของยอดย่อยของแต่ละคน ดังนั้นการแบ่งอาหารแบบ 200:200:100 จึงกำหนดการแบ่งค่าบริการด้วยเช่นกัน การจัดสรรตามจำนวนหัวจะคิดภาษีจาก Chetan อย่างเงียบๆ สำหรับจานที่เขาไม่เคยแตะเลย

ดังนั้นคนที่ไม่ได้สั่งอะไรเลยจึงไม่ต้องจ่ายภาษีและไม่ได้รับส่วนลด น้ำหนักที่ใช้คือยอดย่อยก่อนการปรับ ไม่ใช่ยอดสะสม ซึ่งยังช่วยป้องกันไม่ให้การปัดเศษของการปรับแต่ละครั้งสะสมทบเข้าไปในน้ำหนักของครั้งถัดไป

การปรับถูกนำมาใช้ตามลำดับ ดังนั้นส่วนลดจึงย้ายฐานของ GST

บิลที่ระบุว่า "฿1,000 ลบ 10% บวก GST 5%" จะคิด GST จาก ฿900 และบรรทัด GST เป็น ฿45 สลับสองอย่างนี้ GST จะถูกคิดจาก ฿1,000 ได้เป็น ฿50 การปรับเป็นรายการที่มีลำดับ และเปอร์เซ็นต์ถูกนำไปใช้กับยอดสะสม ณ ตำแหน่งของมันเอง ทั้งสองลำดับเป็นบิลจริง ดังนั้นรายการจึงมีลำดับ ไม่ใช่เป็นเซ็ต

ส่วนลดและ GST เดียวกันในสองลำดับ แสดงฐานที่แต่ละอย่างถูกคิด และยอดรวมที่แต่ละอย่างให้ผล ส่วนลดก่อน GST ก่อน ยอดย่อยของรายการ ฿1,000 ลบ 10% ของ ฿1,000 ส่วนลด ฿100 ฿900 บวก GST 5% ของ ฿900 GST ฿45 ฿945 ยอดรวมบิล ฿945 ยอดย่อยของรายการ ฿1,000 บวก GST 5% ของ ฿1,000 GST ฿50 ฿1,050 ลบ 10% ของ ฿1,050 ส่วนลด ฿105 ฿945 ยอดรวมบิล ฿945 บิลเดียวกัน ลดแบบคงที่ ฿100 แทน 10% ลด ฿100 แล้วค่อย GST ฿945 GST แล้วค่อยลด ฿100 ฿950
เปอร์เซ็นต์สองแบบลงเอยที่ ฿945 เท่ากันเพราะการคูณสลับที่กันได้ แต่บรรทัด GST ต่างกัน: ฿45 กับ ฿50 เปลี่ยนส่วนลดแบบเปอร์เซ็นต์เป็นแบบคงที่ ฿100 แล้วยอดรวมก็แยกจากกันด้วย ฿945 กับ ฿950 ลำดับในที่นี้เป็นเรื่องเลขคณิต ไม่ใช่การนำเสนอ
ทำไมลำดับจึงถูกเก็บไว้อย่างชัดเจน

การปรับแต่ละครั้งมี position ของตัวเอง ลำดับที่อาศัยลำดับการเพิ่มเข้ามา หรืออาศัยตัวสร้าง id ที่เพิ่มขึ้นแบบเรียงตัว จะเปลี่ยนสิ่งที่ทุกคนต้องจ่ายอย่างเงียบๆ หลังจากกู้คืนฐานข้อมูล

การตรวจสอบสามอย่างยืนอยู่ระหว่างการพิมพ์ผิดกับเลขคณิต พูลระบุจำนวนแบบคงที่หรืออัตราเป็นเบสิสพอยต์อย่างใดอย่างหนึ่ง ไม่ใช่ทั้งสองอย่าง เพราะการเก็บทั้งสองอย่างคือการเก็บตัวเลขและที่มาของมันเอง จำนวนที่ติดลบจะถูกปฏิเสธ พร้อมข้อความแสดงข้อผิดพลาดที่ระบุ DISCOUNT เป็นวิธีเขียนการหักลด อัตราที่สูงกว่า 100,000 เบสิสพอยต์จะถูกปฏิเสธเช่นกัน ซึ่งเป็นเพดานที่ตั้งไว้สูงกว่า 10,000 เบสิสพอยต์ที่หมายถึง 100% มาก เพราะการลดร้อยเปอร์เซ็นต์เป็นส่วนลดจริง

ชนิดการปรับทั้งสี่ใน internal/platform/splitcalc และแต่ละอย่างทำอะไรกับยอดสะสม
ชนิดผลต่อยอดสะสมทำไมจึงเป็นชนิดของตัวเอง
TAXเพิ่มเป็นเรื่องถ้อยคำเท่านั้น เหมือนกับการคำนวณ
TIPเพิ่มเป็นเรื่องถ้อยคำเท่านั้น เหมือนกับการคำนวณ
FEEเพิ่มเป็นเรื่องถ้อยคำเท่านั้น เหมือนกับการคำนวณ
DISCOUNTลบชนิดเดียวที่เปลี่ยนเลขคณิต ดังนั้นทิศทางจึงมาจากชนิด ไม่ใช่จากเครื่องหมาย

ยอดรวมมาจากบรรทัดต่างๆ และยอดรวมที่พิมพ์เข้ามาเป็นเพียงเช็กซัม

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

ไคลเอนต์ยังสามารถส่ง amount_minor มาได้ และ Dimesum จะถือว่ามันเป็นเช็กซัม ไม่ใช่คำตอบ การตรงกันหมายความว่าไคลเอนต์อ่านบิลเดียวกัน การไม่ตรงกันจะหยุดค่าใช้จ่ายก่อนที่เงินจะเคลื่อนไหว

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

ทำไม EXACT และรายการจึงถูกปฏิเสธเมื่อใช้ร่วมกัน

EXACT ระบุจำนวนสุดท้ายของสมาชิกแต่ละคน ส่วนรายการคำนวณจำนวนของสมาชิกแต่ละคน การใช้ทั้งสองอย่างพร้อมกันถูกกำหนดเกินความจำเป็น: ไม่ก็ตรงกัน ซึ่งกรณีนี้อย่างหนึ่งจะซ้ำซ้อน หรือไม่ก็ขัดแย้งกัน ซึ่งกรณีนี้ค่าใช้จ่ายมีสองคำตอบและไม่มีกฎบอกว่าอันไหนชนะ Dimesum ปฏิเสธการใช้ร่วมกันตั้งแต่ต้น แทนที่จะตัดสินด้วยกฎลำดับความสำคัญที่ไม่มีใครจำได้

EQUAL PERCENT และ SHARES ล้วนใช้ร่วมกับรายการได้ เพราะแต่ละอย่างเป็นกฎสำหรับหารต้นทุนที่แชร์กัน ไม่ใช่ชุดของจำนวนสุดท้าย

จุดที่ส่วนลดเคยทำให้เสียหนึ่งสตางค์

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

ฟังก์ชัน apportion ของเรามีข้อบกพร่องจริงตรงนี้ การหารจำนวนเต็มของ Go ตัดเศษเข้าหาศูนย์ ดังนั้นยอดรวมที่ติดลบจึงถูกปัดผิดทาง และเศษที่เหลือไม่เคยถูกแจกออกไป: −฿10.00 บนน้ำหนัก 100, 200 และ 300 กลับได้เป็น −฿9.99 หนึ่งสตางค์ที่หายไปจะทำให้บิลที่หักส่วนลดถูกต้องไม่ผ่านการตรวจสอบผลรวมของมันเอง และผู้ใช้จะถูกบอกว่าเลขคณิตของเขาผิด ตอนนี้ยอดรวมที่ติดลบถูกจัดสรรตามขนาดแล้วค่อยกลับเครื่องหมายเป็นลบ

กรอกบิลตามที่มันถูกพิมพ์ออกมา

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

คำถามที่พบบ่อย

แบ่งบิลร้านอาหารยังไงเมื่อมีคนสั่งของแพง?

ใส่จานนั้นเป็นบรรทัดของตัวเองและระบุชื่อคนที่กินมัน ใน Dimesum ส่วนที่เหลือของบิลยังหารตามกฎของค่าใช้จ่ายเอง ซึ่งมักเป็นการหารเท่ากัน ขณะที่บรรทัดที่ระบุชื่อจะตกอยู่กับผู้ถูกกำหนดเท่านั้น จากนั้นภาษีและค่าบริการจะถูกจัดสรรตามยอดย่อยของแต่ละคน ดังนั้นคนที่ไม่ได้กินจานนั้นจึงจ่ายทั้งสองอย่างน้อยลง

ภาษีและทิปควรหารเท่ากันหรือหารตามที่แต่ละคนสั่ง?

หารตามที่แต่ละคนสั่ง Dimesum จัดสรรทุกการปรับตามสัดส่วนของยอดย่อยของแต่ละคน ไม่ใช่ตามจำนวนหัว ในมื้ออาหาร ฿525 ที่คนหนึ่งกินอาหารมูลค่า ฿100 คนนั้นจะรับ ฿5 ของค่าบริการ ฿25 แทนที่จะเป็น ฿8.33 ใครที่ไม่ได้สั่งอะไรเลยก็ไม่ต้องจ่ายภาษีเลย

ลำดับของส่วนลดและภาษีเปลี่ยนราคาบิลไหม?

เปลี่ยน การปรับถูกนำมาใช้ตามลำดับกับยอดสะสม ดังนั้นบิลที่ระบุว่า "฿1,000 ลบ 10% บวก GST 5%" จะคิด GST จาก ฿900 และบรรทัด GST เป็น ฿45 ถ้าใส่ GST ก่อน มันจะถูกคิดจาก ฿1,000 ได้เป็น ฿50 ถ้าใช้ส่วนลดแบบคงที่ ฿100 ยอดรวมก็ต่างกันด้วย ฿945 กับ ฿950

ทำไมใช้จำนวนที่แน่นอนกับบิลแบบแยกรายการไม่ได้?

EXACT ระบุจำนวนสุดท้ายของแต่ละคน ส่วนรายการคำนวณมันออกมา ดังนั้นทั้งสองอย่างรวมกันทำให้ค่าใช้จ่ายเดียวมีสองคำตอบ Dimesum ปฏิเสธการใช้ร่วมกันแทนที่จะเลือกผู้ชนะด้วยกฎลำดับความสำคัญที่ไม่มีใครจำได้ EQUAL, PERCENT และ SHARES ล้วนใช้ร่วมกับรายการได้ เพราะแต่ละอย่างเป็นกฎสำหรับหารบรรทัดที่แชร์กัน ไม่ใช่ชุดของจำนวนสุดท้าย

ต้องพิมพ์ยอดรวมของบิลแบบแยกรายการไหม?

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