当我在CS面试时,我遇到了这个问题。我不知道它,更不用说实现代码......
我可以获得一些提示吗?
P.S。 exp()是函数y = e ^ x和ln()是y = ln(x)
答案 0 :(得分:12)
您可以通过二进制搜索答案找到日志时间的值。这是可能的,因为log X是单调递增的函数。
(由WolframAlpha提供)。
例如,如果我们必须计算的对数值(假设它是X)大于1,则以answer = X的假设开始。提高幂e ^ answer并检查值是否更大现在,根据您获得的值是否大于或小于X,您可以优化您的限制。当你达到答案的合适范围内时,搜索就会停止。
double log(double X){
double lo = 1;
double hi = X;
while(true){
double mid = (lo+hi)/2;
double val = power(e, mid);
if(val > X){
hi = mid;
}
if(val < X){
lo = mid;
}
if(abs(val-X) < error){
return mid;
}
}
}
同样,如果X的值小于1,那么你可以将这种情况减少到我们已经考虑过的情况,即。当X大于1时。例如,如果X = 0.04,那么
log 0.04 = log(4/100) =(log 4) - (log 100)
答案 1 :(得分:8)
如果X为正数,则可以使用Newton's method找到对数。
X_ {0} = 0
X_ {n + 1} = X_ {n} - (exp(X_ {n}) - X)/(exp(X_ {n})
收敛速度非常快。
答案 2 :(得分:5)
调整this answer以使X在范围[0,e]中缩放。我们所知道的关于ln(x)
,ln(x)
的一些事情仅定义为0&lt; 1 {0}。 x,ln(1)=0
,结果可以是从-infinity到+ infinity的任意数字。 ln(x^a) = a * ln(x)
特别是ln(x^(-1)) = - ln(x)
,ln(X/e) = ln(X)-ln(e)
所以ln(X) = ln(X/e) + 1
。
double E = exp(1);
double ln(double X) {
if(X<0) return NaN;
// use recursion to get approx range
if(X<1) {
return - ln( 1 / X );
}
if(X>E) {
return ln(X/E) + 1;
}
// X is now between 1 and e
// Y is between 0 and 1
double lo = 0;
double hi = 1;
while(true){
double mid = (lo+hi)/2;
double val = exp(mid);
if(val > X){
hi = mid;
}
if(val < X){
lo = mid;
}
if(abs(val-X) < error){
return mid;
}
}
}
如果你看一下库中数学函数的实际实现。他们做了很多预缩小工作来缩小输入范围,可能比这里做的更具侵略性。