Bitor XOR ของจำนวนตรรกยะ


19

บทนำ

จำนวนตรรกยะทุกจำนวนระหว่าง 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

ระยะเวลาสูงสุดที่เราต้องการให้การสนับสนุนคืออะไร
Neil

@Neil อะไรที่ทำให้คุณคิดว่าจำนวนสูงสุดดังกล่าวมีอยู่จริง?
orlp

3
หมายเหตุ:ตัวเลขบางตัวมีการขยายไบนารีสองครั้งกล่าวคือตัวเลขเหล่านั้นที่ช่วงเวลาสุดท้ายมีความยาวหนึ่งครั้ง มันเป็นนัยในคำนิยามปัญหาข้างต้นที่เราต้องเลือกการแสดงที่สิ้นสุดใน000...กรณีนี้ (ซึ่งเป็นสิ่งที่เราได้รับถ้าเราใช้อัลกอริทึมด้วยr) ยกตัวอย่างเช่นในกรณีที่5/8, 1/3เราได้รับ23/24เพราะเราเลือกการขยายตัวสำหรับ0.101000... 5/8ถ้าเราเลือกแทนที่จะ0.10011111...เป็น5/8ผลที่ตามมาหลังจากที่แฮคเกอร์จะกลายเป็น19/24เช่นนี้เป็นสิ่งที่ผิด เกี่ยวข้องกับวิกิพีเดีย: 0.999 ...
Jeppe Stig Nielsen

3
@JeppeStigNielsen ประณาม ... ซึ่งหมายความว่าไม่เหมือนกับ XOR ปกติที่(a ^ b) ^ b == aไม่ได้ถือ (19/24 ^ 1/3) ^ 1/3 != 19/24เช่น ที่ทำให้ผมสูญเสียไม่น้อยของความตื่นเต้นเกี่ยวกับ :( นี้
orlp

1
ดูเพิ่มเติมตัวดำเนินการ bitwise มีลักษณะอย่างไรใน 3d ในวิชาคณิตศาสตร์
Ilmari Karonen

คำตอบ:


3

Python 3, 193 164 bytes

def x(a,b,z=0):
 l=[]
 while(a,b)not in l:l+=[(a,b)];z=2*z|(a<.5)^(b<.5);a=a*2%1;b=b*2%1
 p=l.index((a,b));P=len(l)-p
 return((z>>P)+z%2**P*a**0/~-2**(P or 1))/2**p

รับอินพุตเป็นfractions.Fractionชนิดของ Python 3 และส่งออกเช่นกัน

ข้อเท็จจริงที่สนุกสนาน (คุณสามารถแสดงสิ่งนี้ได้โดยใช้ฟังก์ชั่นการสร้าง) หากคุณเปลี่ยน(a<.5)^(b<.5)ไป((a>=.5)and(b>=.5))ด้านบนคุณจะได้รับไบนารีและระหว่างตัวเลขสองตัวที่มีเหตุผล nd(a, b)เรียกสิ่งนี้ว่า ถ้าอย่างนั้นเราก็มีa + b - 2*nd(a, b) = x(a, b)!


แน่นอนความผิดพลาดของฉัน ขอโทษ! (โปรดทราบว่าลิงก์ไปยัง tio ที่รวมอยู่ในคำตอบนั้นยอดเยี่ยม)
Mr. Xcoder

1

จาวาสคริปต์, 141 ไบต์

(p,q,r,s)=>(h=(v,u)=>v%u?h(u,v%u):[a/u,b/u])(b=(g=x=>x%q||x%s?g((x|x/2)+x%2):x)(1),a=(o=b/(b-(b&~-b)),x=p*b/q,y=r*b/s,(x%o^y%o)+(x/o^y/o)*o))

จะไม่ทำงานสำหรับกรณีทดสอบล่าสุด (การล้นจำนวนเต็ม) ใส่หมายเลข 4 สำหรับp/q xor r/sส่งออกอาร์เรย์ด้วยตัวเลขสองตัว สำหรับ testcase คุณควรป้อนข้อมูล0, 00, 1, 0, 1

วิธี:

(ตัวเลขทั้งหมดที่อธิบายไว้ที่นี่อยู่ในรูปแบบไบนารี)

  1. หาจำนวนที่น้อยที่สุดbซึ่งb = 10 ^ p - 10 ^ q (p, q are integers, p > q); and b = 0 (mod q); and b = 0 (mod s);
  2. อนุญาตx = p * b / q, y = r * b / q; แปลงp / q, r / sการx / bและy / b;
  3. อนุญาตo = 10 ^ (p - q) - 1; แยกx, yการ[x % o, x / o], [y % o, y / o]; รับ xor สำหรับแต่ละส่วน[x % o xor y % o, x / o xor y / o]และเข้าร่วมกลับไปที่(x % o xor y % o) + (x / o xor y / o) * o; บริจาคเป็นa;
  4. ถ้าa = 0คำตอบคือ0(หรือ0 / 1); มิฉะนั้นให้u = gcd(a, b); คำตอบคือและ(a/u)(b/u)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.