यदि आप पूर्णांक अंकगणित में मदद करने के लिए फ्लोटिंग-पॉइंट का उपयोग करने के बारे में सोच रहे हैं, तो आपको सावधान रहना होगा।
मैं आमतौर पर जब भी संभव हो एफपी गणना से बचने की कोशिश करता हूं।
फ्लोटिंग-पॉइंट ऑपरेशन सटीक नहीं हैं। आप कभी भी यह सुनिश्चित करने के लिए नहीं जान सकते हैं कि इसका (int)(Math.log(65536)/Math.log(2))
मूल्यांकन क्या होगा । उदाहरण के लिए, Math.ceil(Math.log(1<<29) / Math.log(2))
मेरे पीसी पर 30 है जहां गणितीय रूप से यह बिल्कुल 29 होना चाहिए। मुझे x के लिए कोई मान नहीं मिला जहां (int)(Math.log(x)/Math.log(2))
विफल रहता है (सिर्फ इसलिए कि केवल 32 "खतरनाक" मूल्य हैं), लेकिन इसका मतलब यह नहीं है कि यह काम करेगा किसी भी पीसी पर उसी तरह।
गोलाई में यहाँ सामान्य चाल "एप्सिलॉन" का उपयोग किया जाता है। जैसे (int)(Math.log(x)/Math.log(2)+1e-10)
कभी असफल नहीं होना चाहिए। इस "एप्सिलॉन" का विकल्प एक तुच्छ कार्य नहीं है।
अधिक सामान्य कार्य का उपयोग करते हुए अधिक प्रदर्शन, लागू करने की कोशिश int log(int x, int base)
:
परीक्षण कोड:
static int pow(int base, int power) {
int result = 1;
for (int i = 0; i < power; i++)
result *= base;
return result;
}
private static void test(int base, int pow) {
int x = pow(base, pow);
if (pow != log(x, base))
System.out.println(String.format("error at %d^%d", base, pow));
if(pow!=0 && (pow-1) != log(x-1, base))
System.out.println(String.format("error at %d^%d-1", base, pow));
}
public static void main(String[] args) {
for (int base = 2; base < 500; base++) {
int maxPow = (int) (Math.log(Integer.MAX_VALUE) / Math.log(base));
for (int pow = 0; pow <= maxPow; pow++) {
test(base, pow);
}
}
}
यदि हम लघुगणक के सबसे सीधे-सीधे कार्यान्वयन का उपयोग करते हैं,
static int log(int x, int base)
{
return (int) (Math.log(x) / Math.log(base));
}
यह प्रिंट:
error at 3^5
error at 3^10
error at 3^13
error at 3^15
error at 3^17
error at 9^5
error at 10^3
error at 10^6
error at 10^9
error at 11^7
error at 12^7
...
त्रुटियों से पूरी तरह से छुटकारा पाने के लिए मुझे एप्सिलॉन को जोड़ना पड़ा जो 1e-11 और 1e-14 के बीच है। क्या आप परीक्षण से पहले यह बता सकते थे? मैं निश्चित रूप से नहीं कर सका।