ตำราว่าด้วยตัวเลขและการคำนวณ (筭數書) เป็นหนึ่งในตำราคณิตศาสตร์ที่เก่าแก่ที่สุดของจีน. ตำราซ่วนชู่ชูถูกประพันธ์ขึ้นในยุคราชวงศ์ฮั่นตะวันตก ราว 202-186 ปีก่อนคริสตกาล. ผมได้อ่านตำรานี้ฉบับที่แปลโดยคริสโตเฟอร์ คูลเลน (Christopher Cullen) จากสถาบันนีดแฮม (Needham Institute), สถาบันจีนศึกษาที่เน้นประวัติศาสตร์วิทยาศาสตร์และเทคโนโลยีจีนโบราณ. ผมพบว่าการคำนวณด้วยวิธีแบบจีนโบราณนั้นต่างไปจากแบบตะวันตกที่เราทุกคนถูกฝึกมามาก. เมื่อได้ลองคำนวณโจทย์ง่ายๆ ก็พบว่าสนุกและน่าสนใจดี
ในกระทู้นี้, ผมจะสาธิตการทำเศษส่วนให้เป็นเศษส่วนอย่างต่ำตามวิธีที่แสดงในตำราซ่วนชู่ชู (ซึ่งท่านสามารถดาวน์โหลดได้จาก here).
ข้อความจากหนังสือ
S17,S18(long gap)
(7) Simplifying parts
(a) The method for simplifying parts: Take the numerator from the denominator; in turn take the denominator from the numerator. When the numbers [on the sides of] the numerator and denominator are equal to one another, then you can go on to simplify.(b) Further, the method for simplifying parts:
What can be halved, halve it. Where one [can be counted for each multiple] of some amount, [count] one for [each multiple of] that amount.(c) ・ One method:
Take the numerator of the part from the denominator. [If that is] the lesser take the denominator from the numerator. When [the numbers on the sides of] the numerator and denominator are equal, take that [number] as the divisor. For numerator and denominator complete one for [each time] they accommodate the divisor.Source: Culen, C. (2004). Suanshushu 筭數書: Preliminary matter. The Needham Research Institute, Cambridge UK.
เราสามารถแสดงตัวอย่างการคำนวณตามวิธีข้างต้นได้ดังนี้,
1. ยกตัวอย่างเช่นหากเราต้องการทำเศษส่วน 852/5248 ให้เป็นเศษส่วนอย่างต่ำ, เราจะต้องเริ่มจากการพยายามหักจำนวนข้างต้นด้วยครึ่งนึงของมันจนกว่าจะไม่สามารถหักลบต่อไปได้อีก (หรือพูดในภาษาสมัยใหม่คือการหารด้วย 2 ทั้งเศษและส่วนจนกว่าจะหารต่อไปไม่ได้อีก). ซึ่งในที่สุดเราจะได้เศษส่วน 213/1312 มา.
2. หักลบจำนวนที่มากกว่าด้วยจำนวนที่น้อยกว่าไปเรื่อยๆ จนผลต่าง (ในที่นี้คือ 34) มีค่าน้อยกว่าตัวลบเดิม (ตัวลบเดิมในที่นี้คือ 213). จากนั้นให้นำตัวลบเดิมมาตั้งและลบด้วยจำนวนที่น้อยกว่าไปเรื่อยๆ จำนวนสุดท้ายที่ได้มาก็คือ “ตัวหารร่วมมาก” หรือ ห.ร.ม. (ที่มีนิยามว่า “จำนวนเต็มที่มากที่สุดที่หารทั้งสองจำนวนลงตัว”) ของเศษและส่วนนั่นเอง. นั่นหมายความว่าถ้าหากทำไปถึงที่สุดแล้วได้ 1 แสดงว่าเศษส่วนที่ได้มาในขั้นตอนที่ 1 นั้นเป็นเศษส่วนอย่างต่ำอยู่แล้ว (เพราะ ห.ร.ม. ของเศษและส่วนคือ 1), แต่ถ้าได้จำนวนที่ไม่เท่ากัน 1 ให้นำ ห.ร.ม. นั้นหารทั้งเศษและส่วนจึงจะได้เศษส่วนอย่างต่ำในที่สุด.
ตัวอย่าง
1312 – 213 = 1099
1099 – 213 = 886
886 – 213 = 673
673 – 213 = 460
460 – 213 = 247
247 – 213 = 34
นำตัวลบเดิมมาตั้งและลบด้วยจำนวนน้อยกว่าไปเรื่อยๆ
213 – 34 = 179
179 – 34 = 145
145 – 34 = 111
111 – 34 = 77
77 – 34 = 43
43 – 34 = 9
34 – 9 = 25
25 – 9 = 16
16 – 9 = 7
9 – 7 = 2
7 – 2 = 5
5 – 2 = 3
3-2 = 1
2 – 1 = 1
การทำให้เศษส่วนเป็นเศษส่วนอย่างต่ำตามวิธีข้างต้น ใช้การคำนวณทั้งหมด 22 ครั้ง (จำนวนของการหาร + จำนวนของการลบ). ผู้อ่านอาจรู้สึกว่าการคำนวณง่ายๆ เช่นนี้ต้องใช้ขั้นตอนและเวลามากมาย แต่ในห้วงเวลาที่ยังโลกยังไม่มีเครื่องคิดเลข การคำนวณทางคณิตศาสตร์ด้วยการทำซ้ำๆ (iteration) เป็นวิธีการที่เหมาะสมในทางปฏิบัติมากที่สุด. อย่างไรก็ตามนักคณิตศาสตร์จีนโบราณไม่ได้คำนวณทั้งหมดในหัว (และลูกคิดก็ไม่เหมาะสมกับการคำนวณทางคณิตศาสตร์ที่ซับซ้อน) แต่พวกเขาใช้สิ่งที่เรียกว่า “แท่งคำนวณ” ร่วมกับ “ตารางคำนวณ” (ดูตัวอย่างได้ที่ https://en.wikipedia.org/wiki/Counting_rods). ด้วยเหตุที่คณิตศาสตร์จีนโบราณใช้แท่งคำนวณนี่เอง, สัญลักษณ์ทางคณิตศาสตร์ของจีนโบราณจึงอิงกับแท่งคำนวณและแตกต่างไปจากสัญลักษณ์ทางคณิตศาสตร์แบบตะวันตกที่เรารู้จัก.
ผู้อ่านสามารถลองทำเศษส่วน 162/2016 ซึ่งเป็นตัวอย่างจากตำราให้เป็นเศษส่วนอย่างต่ำดูได้
ผมได้เขียนโค้ดไพธอนเล็กๆ เพื่อแสดงการทำให้เศษส่วนเป็นเศษส่วนอย่างต่ำตามวิธีข้างต้นมาท้ายนี้ด้วย
#!/usr/bin/env python
import sys
def highest_common_factor(numerator, denominator):
"""The highest common factor between the numerator and the denominator
can be calculated according to the algorithm described in Suanshushu S17&S18"""
#1. find the largest part
if numerator > denominator:
larger = numerator
smaller = denominator
elif numerator < denominator:
larger = denominator
smaller = numerator
else:
return 1
global itr
print('iteration = '
+ str(itr) + ', '
+ str(larger) + ' - '
+ str(smaller) + ' = '
+ str(larger-smaller))
#2. subtract recursively until the result is equal to the subtractor
if larger-smaller == smaller:
return smaller
itr += 1
return highest_common_factor(larger-smaller, smaller)
def half_recursive(numerator, denominator):
""" Simplify the fraction as much as possible by diviing
each part with its own half recursively"""
global itr
if not(numerator%2==0 and denominator%2==0):
print('iteration = ' + str(itr)
+ ', numerator = '
+ str(numerator)
+ ', denominator = '
+ str(denominator)
+ '.\n')
itr += 1
return numerator, denominator
print('iteration = ' + str(itr)
+ ', numerator = '
+ str(numerator)
+ ', denominator = '
+ str(denominator)
+ '.\n')
itr += 1
return half_recursive(numerator/2, denominator/2)
def main():
""" Main method """
#1. Simplify the fractions by dividing the numerator and the denominator by their halves as mush as possible
"""What can be halved, halve it. Where one [can be counted or
each mutiple] of some amount, [count] one for [each multiple of] that amount.
Source: Culen, C. Suanshushu. The Needham Research Institute, Cambridge UK"""
global itr
itr = 0 #iternation count
if len(sys.argv) != 2:
print('You did not specify a fraction as an argument. For example, ./simplifying_parts.oy 162/2016\n')
exit()
numerator = int(sys.argv[1].split('/')[0])
denominator = int(sys.argv[1].split('/')[1])
numerator, denominator = half_recursive(numerator, denominator)
#2. Find the highest common diviser by subtracting the greater number with the lower number recursively
"""Take the numerator from the denominator; in turn take the
denominator from the numerator. When the numbers [on the sides of]
the numerator and denominator are equal to one another, then you can go on to simplify.
Source: Culen, C. Suanshushu. The Needham Research Institute, Cambridge UK"""
hcf= highest_common_factor(numerator, denominator)
simplified_fraction = [numerator/hcf, denominator/hcf]
print('The simplified fraction is '
+ str(simplified_fraction[0])
+ '/'
+ str(simplified_fraction[1])
+ '. The calculation requires '
+ str(itr)
+ ' iterations.\n')
if __name__ == "__main__":
main()
แสดงผลตามตัวอย่างดังนี้,
