【问题标题】:Trigonometric Interpolation returns NaN三角插值返回 NaN
【发布时间】:2021-02-03 16:55:57
【问题描述】:

我是一名音乐家,刚接触编程。我在 Max Msp 中使用 JavaScript(因此使用了 bang() 和 post() 函数)来创建三角插值,在给定的等距点之间进行插值(为了测试,只有 [0, 2π 的正弦值)并从相同的点返回值)。当我运行代码时,它返回 NaN,除了 x = 0,因为我的 tau() 函数在这种特殊情况下只返回 1。会不会,它与对 Math.sin 结果求和有关?

var f = new Array(9);
var TWO_PI = 2*Math.PI;

bang();

function bang() {
    for(var i = 0; i < f.length; i++) {
    f[i] = Math.sin(i/f.length*TWO_PI);
    //post("f[" + i + "]: " + Math.round(f[i]*1000)/1000 + "\n");
    }
    
    var points = new Array(f.length);
    for(var i = 0; i < points.length; i++) {
        var idx = i/points.length*TWO_PI;
        points[i] = [i, p(idx)];
    //post("p[" + points[i][0] + "]: " + Math.round(points[i][1]*1000)/1000 + "\n");
    }
    
    console.log("p(2): " + p(2/points.length*TWO_PI) + "\n");
}

function p(x) {
  var result = 0;
  for(var k = 0; k < f.length; k++) {
    result += f[k]*tau(k, x);
  }
  return result;
}

function tau(k, x) {
    var dividend = sinc(1/2*f.length*(x-k/f.length*TWO_PI));
    var divisor = sinc(1/2*(x-k/f.length*TWO_PI));
    var result = dividend/divisor;
    if(f.length%2 == 0) result *= Math.cos(1/2*(x-k/f.length*TWO_PI));
    
    if(x == 0) return 1;
    return result;
}

function sinc(x) {
    return Math.sin(x)/x;
}

【问题讨论】:

  • "...who's new to programming" - 然后尝试使用适当且一致的缩进(您的示例在完全不缩进和缩进之间切换,使用 2 或 4 个空格) .您可能希望跳过 var 的功能范围为 letconst 的块范围。
  • 只是一个提示,但是如果你在你的 tau 方法中添加 console.log(k,x,dividend,divisor,result) 到 2 个返回行之前,你可以看到导致 NaN 的输入范围
  • 在您的 tau 函数中,x 有时等于 k / f.length * TWO_PI,因此您的 sinc 函数除以 0,使 divisor NaN。

标签: javascript math interpolation max-msp-jitter


【解决方案1】:

在你的tau 函数中,如果x 等于k / f.length * TWO_PI(因为x1 / points.length * TWO_PI 的倍数)你的sinc 函数除以0,使得divisor 等于@987654328 @,然后传播。

【讨论】:

  • 哈利路亚!非常感谢您的快速帮助!没有看到这个明显的错误我觉得很愚蠢,但至少代码现在可以工作了:)
【解决方案2】:

在实现 sinc 时必须小心,以避免除以 0。一种方法是,如果 x 足够小,我们可以将 sin(x) 替换为其泰勒级数的前几项,并且所有项可以被 x 整除。

我不知道 javascript,但这是 C 中的函数,以防万一使用

#define SINC_EPS (1e-6)
// for small x, 
// missing sinc terms start with pow(x,4)/120, and value close to 1
// so the error too small to be seen in a double
double  sinc( double x)
{       if ( fabs(x) < SINC_EPS)
        { return 1.0 - x*x/6.0;
        }
        else 
        { return sin(x)/x;
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 2019-06-20
    • 1970-01-01
    • 2014-08-10
    • 2012-08-16
    相关资源
    最近更新 更多