ไม่มีการแตกแขนง


14

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

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

สำหรับปัญหาต่อไปนี้ตัวแปรทั้งหมดเป็นจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อและรหัสที่อนุญาตเท่านั้นคือชุดคำสั่งธรรมดาที่เกี่ยวข้องกับตัวดำเนินการต่อไปนี้เท่านั้น:

+ addition
- subtraction
* multiplication
/ integer division, rounds down, division by 0 not allowed
% modulo
& binary and
| binary or
^ binary exclusive or
>> bitshift right
<< bitshift left

Logic operators, return 1 if the expression is true and 0 if it is false.
== equal
!= not equal
< less than
<= less than or equal
> greater than
>= greater than or equal

Set operator
=

ทุกบรรทัดต้องประกอบด้วยตัวระบุตัวแปรตามด้วยตัวดำเนินการชุดตามด้วยนิพจน์

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

คะแนนกอล์ฟจะนับจำนวนผู้ประกอบการเท่านั้น

ตัวอย่าง:

myvar = ( ( ( foo + 5 ) * bar ) % 7 ) == 3

มีคะแนน 5 ผู้ประกอบการ

คำตอบอาจรวมถึงตัวแปรหลายตัวตามที่ผู้เขียนเห็นว่าเหมาะสม ตัวแปรที่ยังไม่ได้รับการตั้งค่ามีค่า
อนุญาตให้มีมากเกินไปและอันเดอร์โฟลว์ได้ลบจำนวนอันเดอร์โฟลว์ลบทั้งหมดคือ0
3 - 54294967294แม้จะเป็นส่วนหนึ่งของคำสั่งที่มีขนาดใหญ่

ภารกิจที่ 1: สูงสุด

สองค่าAและBมีอยู่ในขอบเขตทำให้RESULTตัวแปรมีค่ามากที่สุดเมื่อโปรแกรมสิ้นสุด

ภารกิจที่ 2: ค่ามัธยฐาน

สามค่าA, BและC, อยู่ในขอบเขตที่ทำให้RESULTตัวแปรมีค่ามัธยฐานของค่าเหล่านั้นเมื่อสิ้นสุดโปรแกรม

ภารกิจที่ 3: รากที่สอง

หนึ่งค่าAมีอยู่ในขอบเขตทำให้RESULTตัวแปรมีสแควร์รูทของAถูกปัดเศษลงเมื่อโปรแกรมยกเลิก

การโพสต์คำตอบสำหรับคำถามเพียงหนึ่งหรือสองคำถามกับบางคนที่เพิ่งพบว่าการแก้ปัญหาที่ถูกต้องจะเป็นเรื่องที่ท้าทาย


ผู้ประกอบการเอกอยู่ที่ไหน ฉันไม่สนใจ-แต่~อาจจะดี (แม้ว่าฉันจะไม่รู้)
John Dvorak

แน่นอนว่าและ0xFFFF_FFFF_FFFF_FFFF ^ x 0 - xฉันจะลืมได้อย่างไร
John Dvorak

@JanDvorak มันทำให้คำอธิบายสั้นตรรกะครบถ้วนไม่ยังเป็นที่น่ารำคาญสวย:! x == 0
aaaaaaaaaaaa

พฤติกรรมของการหารด้วยศูนย์คืออะไร?
John Dvorak

ใน Mathematica (a> b) ให้ผลตอบแทนจริงหรือเท็จ Boole แปลงค่าเท็จเป็น 0 และ True เป็น 1 การใช้งานถูกกฎหมายBoole[a-b]หรือไม่
DavidC

คำตอบ:


5

งาน 3, 23 ตัวเลือก

x = (A >> 16) + A / ((A >> 13) + 511) + 15
x = (x + A/x) >> 1
x = (x + A/x) >> 1
x = (x + A/x) >> 1
RESULT = x - (x > A/x)

การใช้วิธีการของนิวตันเช่นเดียวกับวิธีแก้ปัญหาอื่นทำได้โดยใช้เมล็ดพันธุ์ที่ได้รับการคัดเลือกมากขึ้น บิตแรกA >> 16ทำให้ช่วงบนมีความสุขบิตที่สองA / ((A >> 13) + 511)จะเก็บช่วงกลางของช่วงความสุขและบิตสุดท้าย15ที่ด้านล่างและยังป้องกันการหารด้วยศูนย์ข้อผิดพลาด (15 เป็นค่าที่ใหญ่ที่สุดที่เป็นไปได้ซึ่งช่วยให้0การบรรจบกันอย่างถูกต้อง - ครึ่ง สามครั้งลบด้วยการแก้ไขเท่ากับศูนย์) สำหรับค่าอินพุต225, 275625, 82137969, 2908768489(และค่าใกล้เคียง) เมล็ดเริ่มต้นจะถูกต้อง เคสขอบทั้งหมด (สี่เหลี่ยมที่สมบูรณ์แบบ, สี่เหลี่ยมที่สมบูรณ์แบบ + 1 และสี่เหลี่ยมที่สมบูรณ์แบบ - 1) ในขอบเขต0 .. 2**32-1ได้รับการทดสอบและถูกต้องแล้ว

ไม่กี่ความคิดเห็นเกี่ยวกับกฎ:
มากเกินและอันเดอร์โฟล์ที่ได้รับอนุญาตทั้งหมดตัวเลขติดลบ underflow ดังนั้น 3-5 เป็น 4294967294, แม้จะเป็นส่วนหนึ่งของคำสั่งที่มีขนาดใหญ่

บิตสุดท้ายนั้นกลายเป็นสิ่งที่นักฆ่านวัตกรรม ตอนแรกฉันพยายามแก้ปัญหาโดยใช้รูปแบบทั่วไปของวิธีการของ Halleyแต่รู้ว่ามันไม่ถูกต้องตามข้อ จำกัด ข้างต้น การวนซ้ำ (ตามที่ใช้กับรากที่สอง) คือ:

x = x * (3*A + x*x) / (A + 3*x*x)

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

วิธีการของนิวตันยังมีปัญหา (อย่างน้อยเมื่อจัดการกับจำนวนเต็ม) ว่ามันมักจะไปถึงxเช่นที่A / x - x = 2 - ในกรณีนี้มันจะรวมกันเป็นค่าหนึ่งที่ใหญ่กว่ารูทจำนวนเต็มที่เหมาะสม ซึ่งจะต้องได้รับการแก้ไข; วิธีการของ Halley ไม่ต้องการการแก้ไขเช่นนี้ แต่น่าเสียดายที่ค่าของ3*A + x*xมักจะมีขนาดใหญ่กว่าพื้นที่จำนวนเต็ม 32 บิตที่อนุญาต

มีจำนวนของทั่วไป n อื่น ๆTHอัลกอริทึมราก แต่พวกเขาทั้งหมดแบ่งลักษณะเดียวกันนี้:

x = x + x*(v - x**n)/(v*n)
x = (x*(n+1) - x**(n+1)/v)/n
x = ((n-2)*x + (4*v*x)/(v + x**n))/n
x = x*((n+2)*v + (n-2)*x**n)/(v + x**n)/n
x = ((n-2)*x + (n*x*v)/(v + (n-1)*x**n))/(n-1)
x = ((n-2)*x + x*((n*2-1)*v + x**n)/(v + (n*2-1)*x**n))/(n-1)

x = x + 2*x*(v - x**n)/(v + x**n)/n
x = x + x*31*(v - x**n)/(10*v + 21*x**n)/n
x = x + x*561*(v - x**n)/(181*v + 380*x**n)/n
x = x + x*1153*(v - x**n)/(372*v + 781*x**n)/n

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


ค่อนข้างดี แต่ล้มเหลวสำหรับ 4294967295 สำหรับกฎพวกเขาต้องเข้มงวดเพื่อทำให้มันน่าสนใจ คุณสามารถยืนยันว่าสถานที่ที่แน่นอนสร้างความท้าทายที่สุด แต่ท้ายที่สุดมันสำคัญกว่าที่กฎจะชัดเจนและไม่คลุมเครือกว่าที่พวกเขาอนุญาต
aaaaaaaaaaaa

ฉันไม่คิดว่า Halley น่าจะคุ้มค่าต่อไปจากที่ไกล ๆ คาดว่ามันจะดีขึ้นเล็กน้อยจาก 3 เท่านิวตันก็ทำน้อยกว่า 2 เท่าในทำนองเดียวกันจากการเดาที่ดี Halley จะเพิ่มขึ้นสามเท่า ความแม่นยำนิวตันจะเพิ่มเป็นสองเท่า ดังนั้นหนึ่ง Halley ย้ำเป็นมูลค่าสวยตรงlog(3)/log(2) ~= 1.585ซ้ำของนิวตัน
aaaaaaaaaaaa

@eBusiness ในตอนแรกฉันมี Halley 2 อันซึ่งมีเมล็ดที่ได้รับการเลือกในทำนองเดียวกันซึ่งรวม 25 ops - โดยมีข้อผิดพลาดเมื่อA = 0- ดังนั้นนี่จึงสั้นกว่าจริง ประมาณ4294967295นั่นคือการกำกับ: 65536²≡ 0การวนซ้ำการแก้ไขไม่สามารถแก้ไขได้ ฉันจะดูว่าฉันสามารถหาทางเลือกอื่น
โม่

@eBusiness แก้ไขแล้ว
โม่

สแควร์รูทที่เพรียวบางของแพ็คงานที่ดีและตราชัยชนะอย่างเป็นทางการ
aaaaaaaaaaaa

5

การดำเนินการ 65 (61) (5 + 13 + 47 (43))

ภารกิจ 1 - สูงสุด (A, B)

RESULT = A + (B - A) * (A <= B)

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

ภารกิจ 2 - มิด (A, B, C)

RESULT = A                               \
       + (B - A) * (A > B) ^ (B <= C)    \
       + (C - A) * (A > C) ^ (C <  B)

นี่คือการปรับปรุงโซลูชัน 15-op ก่อนหน้าของฉันซึ่งปรับตัวแปรทั้งสาม - นี่ช่วยลดการลบสองครั้ง แต่มันแนะนำการทดสอบศูนย์กลางอีกครั้ง การทดสอบนั้นง่ายมาก: องค์ประกอบอยู่ตรงกลาง iff อีกอันหนึ่งของทั้งสองอยู่ด้านบน

ภารกิจ 3 - sqrt (A)

X1     = 1024 + A / 2048
X2     = (X1  + A / X1 ) / 2
...
X10    = (X9 + A / X9 ) / 2
RESULT = X16 - (X16 * X16 > A)

รอบที่สิบเอ็ดของการประมาณนิวตัน ค่าคงที่เวทย์มนตร์ที่ 1024 ได้รับการเอาชนะโดยWolframW แล้ว (และ 512 ทำให้เกิดการหารด้วยศูนย์สำหรับ a = 0 ก่อนที่จะมาบรรจบกัน = 2 ** 32 32) แต่ถ้าเราสามารถกำหนด 0/0 เป็นศูนย์การทำซ้ำสิบจะทำงานด้วยค่าเริ่มต้น จาก 512 ฉันยอมรับว่าการอ้างสิทธิ์การทำซ้ำสิบครั้งไม่สะอาดทั้งหมด แต่ฉันยังคงอ้างสิทธิ์ในวงเล็บ ฉันจะต้องตรวจสอบว่าเก้าเป็นไปได้อย่างไรวิธีแก้ปัญหาของ WolframH คือการทำซ้ำเก้าครั้ง


ฉันคิดว่าบรรทัดแรกของภารกิจ 3 ไม่ถูกต้อง: ค่าคงที่ที่สองควรเป็น 4 เท่าของค่าคงที่แรก (เพื่อให้มีนิวตัน "บริสุทธิ์")
Reinstate Monica

@ Wolfram การคาดเดาเริ่มต้นที่ดีกว่าอาจอธิบายได้ว่าทำไมฉันถึงสิ้นเปลืองวงจร คุณมากับ 4 * ที่ไหน ดูเหมือนว่ามีการวนซ้ำสองครั้งในหนึ่งครั้ง
John Dvorak

(1024 + A/1024)/2 == (512 + A/2048)(ซึ่งก็เหมือนX0 = 1024แล้วเริ่มนิวตัน)
Reinstate Monica

วิธีแก้ปัญหาที่ดีสำหรับภารกิจที่ 1 ไข่ของโคลัมบัส
DavidC

@DavidCarraher แน่นอนวิธีแก้ปัญหาที่ถูกต้องจะเป็นMOV RESULT, A; CMP A,B; CMOVA RESULT, B;-)
John Dvorak

5

ตัวดำเนินการ 1: 5

RESULT = B ^ (A ^ B)*(A > B)

2: 13 ตัวดำเนินการ

RESULT = B ^ (A ^ B)*(A > B) ^ (A ^ C)*(A > C) ^ (B ^ C)*(B > C)

3: 27 ตัวดำเนินการ

g = 47|((0x00ffffff & A)>>10)|(A>>14)
r = (g + A/g)/3
r = (r + A/r)>>1
r = (r + A/r)>>1
r = (r + A/r)>>1
RESULT = r - (r*r-1>=A)

5

งาน 3, 39 การปฏิบัติงาน

แก้ไข:เปลี่ยนบรรทัดสุดท้าย ดูความคิดเห็น

นี่คือการดำเนินการตามวิธี Newthon ทดสอบกับสี่เหลี่ยมบวกทั้งหมดและบวกกำลังสองลบหนึ่งและสุ่มหนึ่งล้านตัวเลขในช่วงตั้งแต่ 0 ถึง 2 ^ 32-1 ค่าเริ่มต้นดูเหมือนตลกสั้นสำหรับ(1022 + A/1022) / 2ที่ต้องการจำนวนน้อยที่สุดของการทำซ้ำ (ฉันคิด) และยังทำให้RESULTสำหรับA=0ขวา (ซึ่งจะไม่เป็นกรณีสำหรับ1024แทน1022)

r = (511 + A/2044)
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
r = (r + A/r) / 2
RESULT = r - (r > A/r)

ฉันควรเก็บสำเนาวิธีการของนิวตันที่ด้อยกว่าซึ่งได้รับการปรับให้เหมาะสมกับคุณและโพสต์ในเวลาที่เหมาะสมในภายหลังหรือไม่ จิตใจที่ยิ่งใหญ่คิดเหมือนกันและการแก้ปัญหาแบ่งออกเป็นสองคำตอบนั้นไม่ดี แต่นั่นคือสถานะปัจจุบันของกิจการเพราะคุณยังไม่ได้รับคำตอบ # 2
John Dvorak

@JanDvorak: ขอบคุณที่ถาม ไม่เป็นไรถ้าคุณใส่วิธีที่สั้นกว่าเล็กน้อยลงในคำตอบของคุณ นอกจากนี้ขอขอบคุณที่ให้เครดิตกับฉัน :-)
Reinstate Monica

ลองดีจริงๆ แต่ล้มเหลวในการป้อนข้อมูล 4294965360 ถึง 4294967295
aaaaaaaaaaaa

@eBusiness: ผลลัพธ์อะไรที่คุณได้รับจากอินพุตเหล่านั้น ฉันได้รับ 65535 ในการทดสอบของฉันซึ่งก็โอเค
Reinstate Monica

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