Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การทำงานกับเศษส่วนและเหตุผลใน Ruby

ฉันมีเรื่องจะสารภาพ ฉันเกลียดตัวเลขทศนิยม แน่นอนว่ามีประโยชน์หากคุณเป็นคอมพิวเตอร์ แต่ถ้าคุณเป็นมนุษย์ คุณก็จะเกาหัวในสถานการณ์เช่นนี้:

129.95 * 100
# => 12994.999999999998

สิ่งนี้ไม่เพียงแค่ต้องเผชิญกับความกลมกลืนทางคณิตศาสตร์เท่านั้น แต่ยังเป็น UX ที่แย่อีกด้วย

หากสูตรบอกให้คุณตวงแป้ง 0.37211927843 ถ้วย คุณอาจจะหัวเราะเยาะตัวเองว่าผู้เขียนเป็นคนงี่เง่าอะไร และตวงแป้งไปหนึ่งในสามส่วน

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

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

เหตุผลคืออะไร

สำหรับจุดประสงค์ของเรา "จำนวนตรรกยะ" เป็นเพียงวิธีแฟนซีในการพูดว่า "เศษส่วน" มีสองส่วน:ตัวเศษและส่วน

1/2 # Numerator is 1. Denominator is 2. 
5   # Numerator is 5. Denominator is 1.

ใน Ruby ตัวเลขตรรกยะจะมีประเภทข้อมูลของตัวเอง เช่นเดียวกับจำนวนเต็มและเลขทศนิยม มีสองวิธีในการสร้างเหตุผลใหม่:

3/2r              # This syntax was introduced in Ruby 2.1
1.5.to_r          # Floats can be converted to rationals via `to_r`
"3/2".to_r        # ...so can strings
Rational('3/2')   # This is how we had to do things in the olden days
Rational(3, 2)    # ...see how hard life was?

คณิตศาสตร์อย่างง่าย

เมื่อคุณบวก ลบ คูณ หรือหารจำนวนตรรกยะสองจำนวน ผลลัพธ์จะเป็นจำนวนตรรกยะด้วย

2/3r + 1/3r
# => (1/1)
2/3r - 1/3r
# => (1/3)
2/3r * 1/3r
# => (2/9)
(2/3r) / (1/3r) # We need parens here to avoid confusing the interpreter
# => (2/1)

ตัวดำเนินการทางคณิตศาสตร์อื่นๆ ทั้งหมดทำเหมือนที่คุณคาดหวังเช่นกัน:** , > , < , ฯลฯ..

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

2/3r + 2
# => (8/3)

ค่าประมาณ

สิ่งหนึ่งที่มีประโยชน์มากที่สุดเกี่ยวกับจำนวนตรรกยะคือช่วยให้เราสามารถประมาณค่าและคำนวณได้อย่างง่ายดายในหัวของเรา เพื่อใช้ประโยชน์จากสิ่งนี้ เราต้องทำให้เศษส่วนของเราง่าย 3/2 แทน 3320774221237909/2251799813685248 .

โชคดีที่ Ruby มีวิธีง่ายๆ ในการแปลงตัวเลขที่แม่นยำแต่น่าเกลียดเหล่านี้เป็นตัวเลขโดยประมาณแต่ก็สวยงาม ฉันกำลังพูดถึง rationalize วิธีการ

นี่คือลักษณะ:

# Precise but ugly
(1.47472).to_r
=> (3320774221237909/2251799813685248)

# Less precise, but pretty
(1.47472).to_r.rationalize(0.05)
=> (3/2)

วิธีการหาเหตุผลเข้าข้างตนเองมีหนึ่งอาร์กิวเมนต์ ระบุค่าความคลาดเคลื่อน – ปริมาณความแม่นยำที่คุณต้องการแลกเปลี่ยนเพื่อความเรียบง่าย

วิธีนี้จะค้นหาตัวเลขที่มีตัวส่วนต่ำที่สุดในเกณฑ์ความคลาดเคลื่อนของคุณ ฉันหมายถึงอะไร:

# What's the number with the lowest denominator between 5/10 and 7/10?
(6/10r).rationalize(1/10r)
# => (1/2)

# What's the number with the lowest denominator between 11/20 and 13/20?
(6/10r).rationalize(1/20r)
=> (3/5)

# ..and between 1/10 and 11/10?
(6/10r).rationalize(1/2r)
=> (1/1)

การประมาณน้ำมันดิบ

หากสิ่งที่คุณต้องทำคือหาจำนวนเต็มหรือเลขทศนิยมที่ตรงกับเศษส่วน คุณมีหลายทางเลือก

# Return the nearest integer. 
(6/10r).round
# => 1

# Round down
(12/10r).to_i 
# => 1

ข้อจำกัดของเหตุผล

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

4/0r
ZeroDivisionError: divided by 0

และคุณจะพบกับพฤติกรรมแปลก ๆ หากคุณพยายามถือว่าจำนวนอตรรกยะเป็นจำนวนตรรกยะ

# Umm, isn't the square root of 2 irrational?
Rational(Math.sqrt(2))
# => (6369051672525773/4503599627370496)

# And I'm pretty sure PI is irrational as well.
Rational(Math::PI)
# => (884279719003555/281474976710656)

เราอาจคาดหวังว่าการขอให้ Ruby ปฏิบัติกับจำนวนอตรรกยะเป็นจำนวนตรรกยะจะทำให้เกิดข้อยกเว้นบางประเภท แต่น่าเสียดายที่ Ruby ดูเหมือนจะไม่ฉลาดพอที่จะทำเช่นนี้ แต่จะแปลงค่าประมาณทศนิยมของจำนวนอตรรกยะเหล่านี้เป็นตรรกยะแทน มันไม่ใช่ปัญหาใหญ่แต่เป็นสิ่งที่ต้องระวัง