정수 산술을 돕기 위해 부동 소수점을 사용하려는 경우주의해야합니다.
나는 보통 가능할 때마다 FP 계산을 피하려고 노력합니다.
부동 소수점 연산이 정확하지 않습니다. 당신은 무엇을 (int)(Math.log(65536)/Math.log(2))
평가 할지 확실히 알 수 없습니다 . 예를 들어, Math.ceil(Math.log(1<<29) / Math.log(2))
수학적으로 정확히 29이어야하는 내 PC의 30입니다. x의 값을 찾지 못했습니다.(int)(Math.log(x)/Math.log(2))
32 개의 "위험한"값만 있기 때문에 실패한 작동하지는 않습니다. 모든 PC에서 동일한 방식으로.
여기에서 일반적인 트릭은 반올림 할 때 "엡실론"을 사용하는 것입니다. 처럼(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 사이의 epsilon을 추가해야했습니다. 테스트하기 전에 이것을 말할 수 있습니까? 나는 확실히 할 수 없었다.