【问题标题】:Weird and unexpected results from a simple series一个简单系列的奇怪和意想不到的结果
【发布时间】:2015-07-24 15:47:06
【问题描述】:

我用一个简单的 JS 代码计算以下系列的总和:

b 是一个常数,可以是任何值。 JS 代码尝试查找哪个 minimum 值r(在本例中为 1000 次尝试),这个不等式是有效的:

如果r 低于1.50000,结果就会变得愚蠢。

var pre = 0.0;
var r = 1.50010;
var b = 0.01;

for (var p = 0; p < 1000; p++) {
   var sum = 0;
   for (var i = 0; i <= 33; i++) {
      sum += Math.pow(r, i);
   }

   sum *= b;

   if ((2 * b * Math.pow(r, 34)) > sum) {
      pre = r;
      r -= 0.00001;
      r = parseFloat(r.toFixed(5));
   } else {
      console.log(pre);
      console.log(((2 * b * Math.pow(r + 0.00001, 34)) - sum).toFixed(8));
      break;
   }
}

代码在pre == 1.5 处中断,如果我要强制r = 1.49999,console.log(pre) 将返回0。为什么?

【问题讨论】:

  • 左侧的k + 1 是错误的。据我所知,没有k。在右边,k 只是一个迭代的绑定变量。 k + 1 应该只是 34,对吧?
  • 我的错,是的,33 的值应该会改变。为什么没有k?

标签: javascript math series


【解决方案1】:

代码在 r = 1.5 时停止,因为这是您的不等式有效的最小值(无论如何,在您使用的精度范围内)。如果你从小于这个值开始 r,它会在第一次通过循环时中断,因为 if 语句永远不会为真,所以你永远不会将 pre 设置为 r。

下面的图表显示了不等式的两侧在 r = 1.5 附近发生的情况:

上图代码:

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(1.4, 1.6, 100)
plt.plot(x , 2 * x ** 34, label = '$2r^{34}$')
plt.plot(x , sum([x ** i for i in xrange(34)]), label = '$\sum_{i = 0}^{33}\/ r^i$')
plt.yscale('log')
plt.legend()
plt.show()

此外,如果 b 为正数,则无需在代码中对 b 执行任何操作,因为您将不等式的两边都乘以 b。如果 b 为负数,则需要反转不等式。

哦,还有一件事:对于这种类型的算法,您可能需要考虑更像bisection method 的东西,它每次通过迭代将搜索空间减半。您可以使用 1 和 2 作为端点,因为 1 肯定太低而 2 肯定太高。当不等式两边的差值低于某个阈值时,您会停止。

【讨论】:

  • 为什么它是不等式有效的最小值?
  • @ShinyPhoenix,我添加了一个图表;这有帮助吗?
  • 绝对!谢谢!
  • Amy Teegarden,请问你是如何绘制这两个函数的?
  • 我使用了一个名为 matplotlib (matplotlib.org) 的 python 包。我将代码放在答案中。
【解决方案2】:

我假设当循环中断时,您想要显示不等式左右之间的差异。问题是因为“sum”是来自前一个循环的运行总和,计算不正确。

现在,当您强制 r = 1.49999 时,永远不会执行 if 子句,因此“pre”在第一行开始时保持为零。

你的完整解决方案应该是这样的:

var pre = 0.0;
var r = 1.50010;
var b = 0.01;

for (var p = 0; p < 1000; p++) {
   var sum = 0;
   for (var i = 0; i <= 33; i++) {
      sum += Math.pow(r, i);
   }

   sum *= b;

   var diff = (2 * b * Math.pow(r, 34) - sum).toFixed(8);
   console.log('diff: ' + diff);
   if ((2 * b * Math.pow(r, 34)) > sum) {
      pre = r;
      r -= 0.00001;
      r = parseFloat(r.toFixed(5));
   } else {
      console.log('--breaking--');
      console.log(pre);
      //console.log(((2 * b * Math.pow(r + 0.00001, 34)) - sum).toFixed(8));
      break;
   }
}

输出是:

diff: 3.91098781
diff: 3.52116542
diff: 3.13150396
diff: 2.74200338
diff: 2.35266364
diff: 1.96348468
diff: 1.57446646
diff: 1.18560893
diff: 0.79691205
diff: 0.40837575
diff: 0.02000000
diff: -0.36821526
--breaking--
1.5

【讨论】:

  • 哦,原来如此!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 2014-05-24
  • 1970-01-01
  • 2014-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多