手动计算对数

时间:2018-05-14 17:01:04

标签: javascript math numbers integer logarithm

我想手工计算mathematical logarithm"" ...

...其中代表 logarithmBase 代表值。

一些例子(参见Log calculator):

The base 2 logarithm of 10 is 3.3219280949

The base 5 logarithm of 15 is 1.6826061945

...

不过 - 我不想使用已经实现的函数调用,例如Math.ceil, Math.log, Math.abs, ...,因为我想要一个干净的原生解决方案,只处理+-*/和一些循环。

这是我到目前为止的代码:



function myLog(base, x)  {
  let result = 0;
  do {
    x /= base;
    result ++;
  } while (x >= base)
  return result;
}

let x = 10,
    base = 2;

let result = myLog(base, x)
console.log(result)




但似乎上述方法似乎是计算对数N 的正确方法 - 所以任何有关如何修复此代码的帮助都会非常感激。

感谢一百万提前的乔纳斯。

2 个答案:

答案 0 :(得分:0)

第一种方法:使用常量表。

首先将参数标准化为1到2之间的数字(这可以通过根据需要乘以或除以2来实现 - 保持这些操作的计数)。为了提高效率,如果值可以跨越多个数量级,而不是相等的因子,则可以使用平方序列,2,4,16,256 ......,然后在将括号括起来时进行二分法搜索。

F.i。如果指数16 = 2 ^ 4有效但不是256 = 2 ^ 8,则根据结果尝试2 ^ 6,然后是2 ^ 5和2 ^ 7中的一个。如果最终指数是2 ^ d,则线性搜索采用O(d)运算,而几何/二分法搜索仅采用O(log d)。为了避免分歧,建议保留一个负面表格。

标准化后,您需要优化尾数。将值与√2进行比较,如果较大则乘以1 /√2。这使得值介于1和√2之间。然后比较√√2,依此类推。当你去的时候,当比较返回更大时,你将权重1 / 2,1 / 4,......添加到指数中。

最后,指数是2的对数。

示例:lg 27

with open('result.csv','w',newline='') as f:
    w = csv.writer(f)
    w.writerow(['NAME','ADDRES','MOBILE','EMAIL']) # write header once
    entries = soup.find_all('div', class_='deleadres')
    for entry in entries: # loop over all `.deleadres` elements
        dname = entry.find('div', class_="delrname").text
        dadres = entry.find('p').text
        dmobile = entry.find('div', class_="clearfix").text
        demail = entry.find('div', class_="mobno").text
        w.writerow([dname,dadres,dmobile,demail]) # write data rows for each entry

真正的价值是4.7549。

请注意,您可以与其他基地合作,尤其是e。在某些情况下,base 2允许快捷方式,这就是我使用它的原因。当然,平方根应该制成表格。

第二种方法:使用泰勒系列。

在标准化步骤之后,您可以使用标准系列

27 = 2^4 x 1.6875

1.6875 > √2 = 1.4142 ==> 27 = 2^4.5 x 1.1933

1.1933 > √√2 = 1.1892 ==> 27 = 2^4.75 x 1.0034

1.0034 < √√√2 = 1.0905 ==> 27 = 2^4.75 x 1.0034

...

收敛于log(1 + x) = x - x²/2 + x³/3 - ... 。 (注意:我们现在有自然对数。)

由于收敛对于接近1的值来说太慢,建议使用上述方法将范围缩小到[1,√2]。然后每个新术语都会带来一点新的准确性。

或者,您可以将该系列用于log((1 + x)/(1 - x)),即使对于参数2,也可以提供良好的收敛速度。请参阅https://fr.wikipedia.org/wiki/Logarithme_naturel#D%C3%A9veloppement_en_s%C3%A9rie

示例:x = 1.6875,y = 0.2558和

|x| < 1

答案 1 :(得分:-1)

您可以使用递归方法:

 const log = (base, n, depth = 20, curr = 64, precision = curr / 2) => 
   depth  <= 0 || base ** curr === n 
      ? curr
      : log(base, n, depth - 1, base ** curr > n ? curr - precision : curr + precision, precision / 2);

可用作:

log(2, 4) // 2
log(2, 10) // 3.32196044921875

您可以通过更改depth来影响精确度,并且可以使用curr更改已接受值的范围(当前为~180)

工作原理:

如果我们已达到所需深度或已找到准确值:

 depth  <= 0 || base ** curr === n 

然后它只返回curr并完成。否则,它会检查我们想要找到的对数是低于还是高于当前对数:

         base ** curr > n

然后它将继续以递归方式搜索值 1)将depth降低一个 2)按当前精度增加/减少curr 3)精度较低

如果您讨厌函数式编程,那么这是一个命令式版本:

  function log(base, n, depth = 20) {
   let curr = 64, precision = curr / 2;
   while(depth-- > 0 && base ** curr !== n) {
     if(base ** curr > n) {
       curr -= precision;
     } else {
       curr += precision;
     }
     precision /= 2;
    }
    return curr;
  }

顺便说一句,我使用的算法称为"logarithmic search",通常称为“二分搜索”。