มีทางเลือกที่ไม่ใช่ลอยเพื่อ pow ()?


9

ฉันได้ทำการอ้างอิงภาษา LANGUAGE ในเว็บไซต์ Arduinoและฉันไม่สามารถหาสิ่งที่ไม่เทียบเท่ากับที่pow() ฉันจะต้องหายไปบางสิ่งที่ใหญ่ แต่สำหรับชีวิตของฉันฉันนิ่งงัน! ฉันพบpow()ในคอลัมน์ FUNCTIONS ใต้หัวข้อ Math (เหมือนที่ฉันคาดไว้) แต่มันบอกว่าทั้งพารามิเตอร์ [base] และ [exponent] เป็นทั้งคู่ (float) และมีเพียงหกรายการอื่น ๆ ภายใต้หัวข้อคณิตศาสตร์; ดูเหมือนว่าพวกเขาจะไม่เป็นรุ่นจำนวนเต็ม สิ่งที่ฉันต้องการทำคือสร้างพลังของ 2 โดยใช้เลขชี้กำลังจาก 0 ถึง 10 เช่น 2 ^ 0 = 1 จากนั้น 2 ^ 1 = 2 จากนั้น 2 ^ 2 = 4 จากนั้น 2 ^ 3 = 8 จากนั้น 2 ^ 4 = 16 แล้ว 2 ^ 5 = 32 จากนั้น 2 ^ 6 = 64 แล้ว 2 ^ 7 = 128 จากนั้น 2 ^ 8 = 256 จากนั้น 2 ^ 9 = 512 จากนั้น 2 ^ 10 คือ 1024

การใช้ลอยวิธีเดียวที่ฉันสามารถทำได้? ฉันเริ่มรู้สึกว่าฉันกำลังขัดแย้งกับความเป็นจริงและนับยาของฉันจริง ๆ แต่ฉันก็ถูกต้องแล้ว ให้ฉันขอโทษล่วงหน้าสำหรับการกำกับดูแลที่ยิ่งใหญ่นี้ซึ่งฉันเสียเวลากับคุณ แต่ฉันได้อ่านแท็กทั้งหมด 9 หน้าและได้ทำการค้นหาที่เคยคิดมาแล้ว ฉันจะยอมรับว่าฉันไม่ได้ใช้เวลามากขนาดนั้น แต่ฉันแน่ใจว่านี่จะเป็นเพียงห้านาที!


2
สำหรับกรณีทั่วไปของจำนวนเต็มธาร () ดูstackoverflow.com/questions/101439/... สำหรับพลังของ 2 เพียงใช้กะ
Peter Cordes

คำตอบ:


8

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

การคูณตัวเลขด้วยกำลังสองสามารถทำได้โดยการใช้การเลื่อนซ้าย ( <<) ซึ่งจะเปลี่ยนตัวเลขของการแทนเลขฐานสองของตัวเลข (เช่นบิต) ไปทางซ้ายอย่างแท้จริง ในฐานสองการขยับบิตหนึ่งตำแหน่งไปทางซ้ายจะเหมือนกับการคูณด้วย 2 เช่นเดียวกับในฐาน 10 การเลื่อนตำแหน่งหนึ่งตำแหน่งไปทางซ้ายจะเหมือนกับการคูณด้วย 10 สำหรับคำอธิบายทั้งหมดของตัวเลื่อนกะซ้ายใน C ++ ดูคำตอบนี้บนกองมากเกิน

เป็นสิ่งสำคัญที่จะต้องทราบว่าการเลื่อนซ้ายอาจทำให้ข้อมูลสูญหายได้ บิตที่เลื่อนออกจากจุดสิ้นสุดจะหายไป เพราะคุณจะต้องอำนาจของ 2 ถึง 10 คุณมีความปลอดภัยเมื่อทำงานกับจำนวนเต็มลงนามซึ่งมีมูลค่าสูงสุด2^15-1ใน Arduino Uno

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

int pow2(int p){
    return 1 << p;
}

ข้อผิดพลาด: มันสามารถไปได้ถึง 2 ^ 32-1 unsigned longหากคุณใช้
Dat Ha

@DatHa ขอบคุณฉันดูเหมือนจะสูญเสียคำว่า "ลงนาม" ในระหว่างการแก้ไข แก้ไขแล้ว.
Jason Clark

1
มันสามารถผ่านไปได้ 2 ^ 32 - 1 หากคุณใช้การคำนวณเลขจำนวนเต็มความแม่นยำโดยพลการ
Dat Han Bag

ฉันต้องการโดยเฉพาะอย่างยิ่งที่จะรู้ว่าทำไมผลลัพธ์ของการแปลงจำนวนเต็มจากผลลัพธ์ของ pow () ไม่ทำงานสำหรับพลังของ 2 สำหรับฉัน pow (2,3) ส่งคืน 8.00 แต่ในขณะที่ int (8.00) กลับ 8 , int (pow (2,3)) ส่งคืน 7!
KDM

1

จะทำงานร่วมกับint, double, และlong และควรทำงานเช่นกัน คุณไม่จำเป็นต้องใช้ลอยเท่านั้นfloatunsigned longunsigned int

หวังว่ามันจะช่วย!


เหตุผลที่คำตอบข้างต้นเป็นเพราะชุดของจำนวนจริง (ซึ่งมีจำนวนลอย) มีชุดจำนวนเต็ม
Dat Han Bag

@DatHanBag: และที่สำคัญทุก 32 doubleบิตจำนวนเต็มเป็นสิ่งแสดงโดย ที่จริงแล้วเนื่องจากจุดลอยตัวของ IEEE นั้นขึ้นอยู่กับการแทนเลขฐานสองของ mantissa / เลขชี้กำลังพลังงานทั้งหมดของ 2 ควรจะสามารถแทนได้อย่างแน่นอนแม้เกิน 2 ^ 53 (จุดที่doubleไม่สามารถแทนจำนวนเต็มทุกตัวได้โดย 1 หน่วยในตำแหน่งสุดท้ายของ mantissa มากกว่า 1.0)
Peter Cordes

@PeterCordes ใช่ฉันรู้แล้ว บางทีฉันควรจะพูดว่า "ชุดขอบเขต" เมื่อพูดถึงชุดเลขจำนวนเต็มและลอยสำหรับ arduino ในความคิดเห็นของฉันเกี่ยวกับคำตอบของ
Dat Han Bag

4
นี่เป็นคำตอบที่ถูกต้องสำหรับคำถามทั่วไปเกี่ยวกับการใช้pow()จำนวนเต็ม แต่ AFAICT arduino ไม่มีจุดลอยตัวของฮาร์ดแวร์ดังนั้นมันจึงเป็นคำตอบที่แย่มาก การpow()ดำเนินการจำนวนเต็มเช่นนี้ที่ทำงานใน log2 (n) เวลาคูณและเพิ่มการสะสมผลลัพธ์อาจจะทำงานได้ดีขึ้นและแน่นอนว่าการไม่ทำงานบิตที่เปลี่ยนไปใช้กำลัง 2 เพียงแค่ทำให้นี่เป็นคำตอบที่น่ากลัวสำหรับคำถามนี้
Peter Cordes

1
@ PeterCordes "ดังนั้นจึงเป็นคำตอบที่น่ากลัว" - ยอมรับว่ามันเป็นคำตอบง่ายๆที่มีคุณภาพต่ำ pow () สามารถคำนวณได้อย่างแน่นอนใน log2 (n) - วิธีง่าย ๆ ที่เรียนในโรงเรียน คุณสามารถทำได้ดีขึ้นด้วยการแปลงฟูริเยร์สำหรับจำนวนเต็มขนาดใหญ่จริง ๆ ตัวอย่างเช่น แต่ OP อาจยอมรับและชอบ
Dat Han Bag
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.