আপনি যদি পূর্ণসংখ্যার গাণিতিক সাহায্যে ভাসমান-পয়েন্ট ব্যবহার করার কথা ভাবছেন তবে আপনাকে সতর্কতা অবলম্বন করতে হবে।
আমি সাধারণত যখনই সম্ভব এফপি গণনা এড়ানোর চেষ্টা করি।
ভাসমান-পয়েন্ট অপারেশনগুলি সঠিক নয়। আপনি কখনই (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 এর মধ্যে রয়েছে। আপনি পরীক্ষা করার আগে এই বলতে পারে? আমি অবশ্যই পারিনি।