บทนำ
จำนวนตรรกยะทุกจำนวนระหว่าง 0 ถึง 1 สามารถแสดงเป็นลำดับตามลำดับในที่สุดของบิต ตัวอย่างเช่นการแทนเลขฐานสองของ 11/40 คือ
0.010 0011 0011 0011 ...
ที่0011
เป็นส่วนหนึ่งซ้ำไปเรื่อย ๆ วิธีหนึ่งในการค้นหาการแสดงนี้คือต่อไปนี้ เริ่มต้นด้วยr = 11/40จากนั้นเพิ่มเป็นสองเท่าและใช้ส่วนที่เป็นเศษส่วนบันทึกเมื่อมันไปด้านบน 1 เมื่อค่าของrซ้ำคุณรู้ว่าคุณได้เข้าสู่ลูป
1. r = 11/40
2. 2*r = 11/20 < 1 -> next bit is 0, r = 11/20
3. 2*r = 11/10 >= 1 -> next bit is 1, r = 2*r - 1 = 1/10
4. 2*r = 1/5 < 1 -> next bit is 0, r = 1/5
5. 2*r = 2/5 < 1 -> next bit is 0, r = 2/5
6. 2*r = 4/5 < 1 -> next bit is 0, r = 4/5
7. 2*r = 8/5 >= 1 -> next bit is 1, r = 2*r - 1 = 3/5
8. 2*r = 6/5 >= 1 -> next bit is 1, r = 2*r - 1 = 1/5, same as in 4.
The loop 5. -> 6. -> 7. -> 8. now repeats.
ในการรับจากสตริงไบนารีกลับไปที่ 11/40 คุณสามารถใช้สูตร
(int(prefix) + int(suffix)/(2^len(suffix) - 1)) / 2^len(prefix)
ที่prefix
เป็นส่วนเริ่มต้น010
, suffix
เป็นส่วนหนึ่งของการทำซ้ำ0011
และint
แปลงสตริงไบนารีจำนวนเต็ม
ด้วยการเป็นตัวแทนสองแบบนี้เราสามารถทำการดำเนินการ XOR ในระดับบิตได้ ลำดับที่เกิดขึ้นจะเป็นระยะดังนั้นจึงแสดงถึงจำนวนตรรกยะ
สำหรับตัวเลขที่มีเหตุผลบางตัวมีการแทนเลขฐานสองสองตัว
1/4 = 0.010000000...
= 0.001111111...
ตัวเลือกระหว่างสิ่งเหล่านี้สามารถส่งผลต่อผลลัพธ์ของ bitor XOR ในกรณีเหล่านี้เราใช้การเป็นตัวแทนแบบเดิมซึ่งมี 0s ไม่ จำกัด จำนวนมาก
งาน
อินพุตของคุณเป็นตัวเลขสองเหตุผลในช่วงครึ่งเวลาที่เปิด [0,1) ผลลัพธ์ของคุณจะเป็นผลของการดำเนินการ XOR ระดับบิตที่ใช้กับอินพุตซึ่งแสดงเป็นจำนวนตรรกยะ โปรดทราบว่าเอาต์พุตสามารถเป็น 1 ได้แม้ว่าจะไม่มีอินพุตใดก็ตาม
รูปแบบที่แน่นอนของอินพุตและเอาต์พุตมีความยืดหยุ่น แต่แต่ละจำนวนตรรกยะควรแสดงด้วยจำนวนเต็มสองจำนวนคือตัวเศษและส่วน (ยกเว้น 0 และ 1 ซึ่งสามารถแสดงเป็น0
และ1
หากต้องการ) คุณสามารถสันนิษฐานได้ว่าอินพุตนั้นแสดงด้วยคำต่ำสุด เอาต์พุตจะต้องแสดงเป็นคำที่ต่ำที่สุด ชนิดจำนวนตรรกยะในตัวเป็นรูปแบบที่ยอมรับได้ตราบใดที่มันเป็นไปตามข้อ จำกัด เหล่านี้ คุณสามารถเพิกเฉยต่อขอบเขตของจำนวนเต็มที่ภาษาของคุณกำหนด แต่อัลกอริทึมของคุณควรใช้กับตัวเลขที่มีเหตุผลทั้งหมด
จำนวนไบต์ต่ำสุดชนะ ใช้กฎมาตรฐานของกอล์ฟ
ตัวอย่าง
พิจารณาอินพุต 11/40 และ 3/7 เราเขียนเป็นตัวแทนของพวกเขาเหนือผู้อื่น, delimiting |
ส่วนการทำซ้ำโดยท่อ จากนั้นเราแยกส่วนที่ทำซ้ำที่มีความยาวเท่ากันและใช้ XOR ระดับบิตกับพวกเขาและส่วนก่อนหน้าพวกเขา
11/40 = 0. 0 1 0|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 ...
3/7 = 0.|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|...
-> 0. 0 0 1|0 1 0 1 1 1 1 0 1 0 0 0|0 1 0 1 1 1 1 0 1 0 0 0|0 1 0 ...
จำนวนตรรกยะที่เกิดขึ้นคือ 89/520
กรณีทดสอบ
0 0 -> 0
1/2 1/2 -> 0
1/2 1/4 -> 3/4
1/3 2/3 -> 1
1/2 3/4 -> 1/4
5/8 1/3 -> 23/24
1/3 1/5 -> 2/5
15/16 3/19 -> 257/304
15/16 257/304 -> 3/19
3/7 11/40 -> 89/520
5/32 17/24 -> 59/96
16/29 16/39 -> 621001733121535520/696556744961512799
000...
กรณีนี้ (ซึ่งเป็นสิ่งที่เราได้รับถ้าเราใช้อัลกอริทึมด้วยr
) ยกตัวอย่างเช่นในกรณีที่5/8, 1/3
เราได้รับ23/24
เพราะเราเลือกการขยายตัวสำหรับ0.101000...
5/8
ถ้าเราเลือกแทนที่จะ0.10011111...
เป็น5/8
ผลที่ตามมาหลังจากที่แฮคเกอร์จะกลายเป็น19/24
เช่นนี้เป็นสิ่งที่ผิด เกี่ยวข้องกับวิกิพีเดีย: 0.999 ...
(a ^ b) ^ b == a
ไม่ได้ถือ (19/24 ^ 1/3) ^ 1/3 != 19/24
เช่น ที่ทำให้ผมสูญเสียไม่น้อยของความตื่นเต้นเกี่ยวกับ :( นี้