ปัญหาของคุณอยู่ภายใต้การระบุคุณต้องถอยกลับและถามคำถาม
- อินพุตของคุณประเภทใด
- คุณต้องการผลงานประเภทใด
- สำหรับผลลัพธ์ที่น้อยกว่า 1 คุณต้องการปัดเศษเป็นอย่างไร คุณต้องการอำนาจที่แท้จริงของ 10 หรือการประมาณจุดลอยตัวของอำนาจของ 10? คุณตระหนักดีว่าพลังเชิงลบ 10 ไม่สามารถแสดงได้อย่างแน่นอนในจุดลอยตัวใช่มั้ย สมมติว่าตอนนี้คุณต้องการการประมาณค่าจุดลอยตัวของกำลัง 10
- หากอินพุตนั้นมีกำลังเท่ากับ 10 (หรือประมาณจุดลอยตัวที่ใกล้เคียงที่สุดของกำลัง 10) เอาต์พุตควรเหมือนกันกับอินพุตหรือไม่? หรือมันควรจะเป็นพลังงานต่อไปของ 10 ขึ้นไป? "10 -> 10" หรือ "10 -> 100"? สมมติว่าตอนนี้เป็นอดีต
- ค่าอินพุตของคุณสามารถเป็นค่าที่เป็นไปได้ของประเภทที่เป็นปัญหาหรือไม่ หรือพวกเขาถูก จำกัด มากขึ้น
ในอีกคำตอบหนึ่งก็เสนอให้ใช้ค่าลอการิทึมจากนั้นปัดเศษ (ฟังก์ชันเพดาน) แล้วยกกำลัง
def nextpow10(n):
return 10 ** math.ceil(math.log10(n))
น่าเสียดายที่นี่มีข้อผิดพลาดในการปัดเศษ ประการแรก n ทั้งหมดจะถูกแปลงจากชนิดข้อมูลใด ๆ ที่เกิดขึ้นให้เป็นเลขทศนิยมที่มีความแม่นยำสองเท่าซึ่งอาจทำให้เกิดข้อผิดพลาดในการปัดเศษจากนั้นการคำนวณลอการิทึมจะแนะนำข้อผิดพลาดในการปัดเศษเพิ่มเติมทั้งในการคำนวณภายใน
เช่นนี้ฉันใช้เวลาไม่นานในการหาตัวอย่างที่ให้ผลลัพธ์ที่ไม่ถูกต้อง
>>> import math
>>> from numpy import nextafter
>>> n = 1
>>> while (10 ** math.ceil(math.log10(nextafter(n,math.inf)))) > n:
... n *= 10
...
>>> n
10
>>> nextafter(n,math.inf)
10.000000000000002
>>> 10 ** math.ceil(math.log10(10.000000000000002))
10
นอกจากนี้ยังเป็นไปได้ในทางทฤษฎีที่มันจะล้มเหลวในทิศทางอื่นแม้ว่ามันจะยากกว่าที่จะกระตุ้น
ดังนั้นสำหรับวิธีแก้ปัญหาที่มีประสิทธิภาพสำหรับการลอยตัวและ ints เราจำเป็นต้องสมมติว่าค่าลอการิทึมของเรานั้นเป็นค่าโดยประมาณเท่านั้นและเราต้องทดสอบความเป็นไปได้สองอย่าง บางสิ่งบางอย่างตามแนวของ
def nextpow10(n):
p = round(math.log10(n))
r = 10 ** p
if r < n:
r = 10 ** (p+1)
return r;
ฉันเชื่อว่ารหัสนี้ควรให้ผลลัพธ์ที่ถูกต้องสำหรับข้อโต้แย้งทั้งหมดในขอบเขตที่แท้จริงของโลก มันจะแตกสำหรับจำนวนจุดที่ไม่ใช่จำนวนเต็มและไม่ลอยจำนวนมากหรือเล็กมากเนื่องจากปัญหาในการแปลงเป็นจุดลอย งูใหญ่กรณีพิเศษอาร์กิวเมนต์จำนวนเต็มไปยังฟังก์ชั่น log10 ในความพยายามที่จะป้องกันไม่ให้ล้น แต่ก็ยังมีจำนวนเต็มขนาดใหญ่เพียงพอก็อาจเป็นไปได้ที่จะบังคับให้ผลลัพธ์ที่ไม่ถูกต้องเนื่องจากข้อผิดพลาดในการปัดเศษ
เพื่อทดสอบการใช้งานสองแบบฉันใช้โปรแกรมทดสอบต่อไปนี้
n = -323 # 10**-324 == 0
while n < 1000:
v = 10 ** n
if v != nextpow10(v): print(str(v)+" bad")
try:
v = min(nextafter(v,math.inf),v+1)
except:
v += 1
if v > nextpow10(v): print(str(v)+" bad")
n += 1
สิ่งนี้พบความล้มเหลวมากมายในการใช้งานแบบไร้เดียงสา แต่ไม่มีในการใช้งานที่ปรับปรุงใหม่
10
ได้log10
ดี