【问题标题】:Is there a one-line function that generates a triangle wave?有没有产生三角波的单线函数?
【发布时间】:2015-07-27 18:46:53
【问题描述】:

生成锯齿波的方式类似。它不必是连续的。

这就是我的意思:

int m = 10;
int x = 0;
int i = 0;
while (i < m*3) {
    printf("%d ", x);
    x++;
    x = x % m;
    i++;
}

生成一个序列 0..9,3 次,如下所示:

请注意,峰右侧的斜率只是一个图形工件

本例中的单行是 x = i++ % m


我想要的是这个:

如果您知道其他波形(正弦波、方波)的单线,那也很好。

更新:每个人的回答都非常有帮助,我有一个后续问题。

将什么添加到三角波函数以使线的斜率像这样弯曲或弯曲:

谢谢大家,您多样的回答帮助我从更大的角度看待问题。特别感谢 Noldorin 将方程扩展到二次曲线。

【问题讨论】:

  • 为什么他们必须是“单线”?
  • 我想你的意思是x = x++ % m
  • @Neil 因为我知道如何使用 for 循环和 if 语句来完成它们。我想要一种更优雅的方式来做这些事情。 @Noldorin 新手学习一些东西
  • @willc2:我现在已经在你的问题中解决了这个问题。希望你不要介意。
  • (再看你的代码,我相信你的意思是x = i++ % m。)

标签: c


【解决方案1】:

三角波

y = abs((x++ % 6) - 3);

这给出了一个周期为 6 的三角波,在 3 和 0 之间振荡。

方波

y = (x++ % 6) < 3 ? 3 : 0;

这给出了一个周期为 6 的规则方波,在 3 和 0 之间振荡。

正弦波

y = 3 * sin((float)x / 10);

这给出了一个周期为 20 pi 的正弦波,在 3 和 -3 之间振荡。


更新:

曲线三角波

要获得具有曲线而不是直线的三角波的变化,您只需在方程中引入一个指数以使其成为二次方。

凹曲线(即x^2形状):

y = pow(abs((x++ % 6) - 3), 2.0);

凹曲线(即sqrt(x)形状):

y = pow(abs((x++ % 6) - 3), 0.5);

除了使用pow 函数,您可以简单地定义一个square 函数并在math.h 中使用sqrt 函数,这可能会稍微提高性能。

另外,如果您想让曲线更陡/更浅,只需尝试更改索引即可。


在所有这些情况下,您应该能够轻松地调整常数并在正确的位置添加比例因子以给出给定波形的变化(不同的周期、幅度、不对称等)。

【讨论】:

  • 请注意,我的 x 与问题中的 x 不对应。我这里使用的 x 代表沿 x 轴的常规值,同样 y 代表沿 y 轴的值。这里的 x 似乎是您问题中的 i。
  • 我可以添加这些波形以获得更复杂的波形,是吗?
  • 那个三角波不是在3到0之间振荡吗?
  • @willc2:是的,当然。 :) 如果您想知道如何获得另一个特定波形,请问,我可以提出一些建议 - 但是这些提供了很好的起点。
  • @JoanVenge:减去一个常数是为了偏移曲线的位置,使其围绕 x 轴对称。因此 3 实际上是幅度(峰谷距离的一半,即 6)。 pow(..., 2.0) 是形成二次曲线。
【解决方案2】:

扩展 Eric Bainville 的回答:

y = (A/P) * (P - abs(x % (2*P) - P) )

其中 x 是运行整数,y 是三角波输出。 A 是波的幅度,P 是半周期。例如,A=5 将产生一个从 0 到 5 的波; P=10 将产生一个周期为 20 的波。波从 y=0 开始,x=0。

请注意,除非 P 是 A 的因子,否则 y 将是一个浮点数。 而且,是的,对于数学纯粹主义者来说:从技术上讲,A 是波幅的两倍,但是看看下面的图片,你就会明白我的意思了。

可视化:

【讨论】:

  • 这是一个更好的答案,纯粹是因为它已记录在案。
  • 与 P 相同的公式表示周期,而不是一半:y = (A/(P/2)) * ((P/2) - abs(x % (2*(P/2) - P/2))
【解决方案3】:
x = m - abs(i % (2*m) - m)

【讨论】:

    【解决方案4】:

    我知道这是一篇旧帖子,但对于正在寻找类似内容的任何人,我建议您看看。 http://en.wikipedia.org/wiki/Triangle_wave

    最后一个公式y(x)=(2a/π)arcsin(sin((2π/p)*x))

    或者。

    (2 * amplitudeConstant / Math.PI) * Math.Asin(Math.Sin(2 * (Math.PI / periodConstant) * Convert.ToDouble(variableX)))
    

    【讨论】:

    • OP 指定函数不必是连续的,但如果它确实需要为小数和负值工作,这个版本很有用。
    • 另请注意,它输出负值和正值。
    • 这个答案给出了一个简单的三角波形,没有其他答案的所有调整。简洁明了,谢谢!
    【解决方案5】:
    y = abs( amplitude - x % (2*amplitude) )
    

    改变波长只需要x的一个因素。

    编辑:我所说的幅度实际上不是幅度,而是最大值(即,如果曲线在 0 和 5 之间振荡,则为 5)。数学意义上的幅度是它的一半。但你明白了。

    【讨论】:

    • 这会产生一个“V”波;您需要添加“y = m - y”才能获得三角波
    • 波通常被认为是无限的,因此“V 波”和三角波基本相同。但到目前为止,如果你想要 f(0) = 0,你就必须做一个转变。
    【解决方案6】:

    试试这个:

    x = m - abs(m - 2*(i++ % m))
    

    【讨论】:

      【解决方案7】:

      这是一个周期函数,看起来像一个遥远的正弦近似值;本质上它是一个正弦抛物面,使用 X 平方:

      function  xs ( xx : float ): float{
      
          var xd =Mathf.Abs((Mathf.Abs(xx) % 2.4) - 1.2);
      
          if (  Mathf.Abs(Mathf.Abs(xx) % 4.8)  > 2.4){ 
              xd=(-xd*xd)+2.88;
          }else{
              xd = xd*xd;
          }
      
          return xd;
      
      }
      

      【讨论】:

        【解决方案8】:

        我用一个简单的循环测试了它,你们根本没有回答这个人的问题。剪切和粘贴对人们没有帮助。难怪如此多的大众媒体恶作剧如此成功。对于一个重复他人错误的人来说,这不足为奇。人们甚至对这些错误的答案给予正面评价?!难以置信的!但是,这又与我之前的评论相似。

        首先,我们将向我们的人们解释三角波是什么。好吧,它是一个波,其周期由两个相等的斜坡组成。一个向上倾斜的斜坡和一个与第一个相同但向下倾斜的斜坡与一个锯齿形相反,它具有一个向上倾斜的斜坡或一个向下倾斜的斜坡,在一个反向的 talud 之后重复。

        PS:最后一个给出的“y(x)=(2a/π)arcsin(sin((2π/p)*x))”太复杂了,我们正在寻找一个快速的c++例程所以三角函数是绝对不可能。

        测试例程:

        (...)

        for (byte V=0; V<255; V++)
        {
        unsigned int x = evenramp(V);
        plotRGB(0,0,x,x,x);
        delay(100); // make sure you have your own delay function declared of course
        
        /* use your own graphic function !!! plotRGB(row,column,R,G,B) */
        /* the light intensity will give you the change of value V in time */
        /* all functions suggested as answer give SAWTOOTH and NOT TRIANGLE */
        /* it is a TRIANGLE the man wants */
        }
        
        float triangleattempt(unsigned int x) // place any answered formula after '255 *' behind return.
        {
        return 255 * (255 - abs(255 - 2*(x % 255))); // this will show a SAWTOOTH
        }
        
        //All given answers up to now excluding "function  xs ( xx : float ): float" (this is not the requested one-liner, sorry) that are not a symmetrical triangle wave
        
        // m - abs(i % (2*m) - m); (this is still a SAWTOOTH wave and not a TRIANGLE wave)
        // abs((x++ % 6) - 3); (this is still a SAWTOOTH wave and not a TRIANGLE wave)
        // abs(amplitude - x % (2*amplitude)); (this is still a SAWTOOTH wave and not a TRIANGLE wave)
        

        => 我找到了一个以数学符号准确说明答案的来源:http://mathworld.wolfram.com/TriangleWave.html

        我已经在一个名为 KmPlot 的 Linux 程序上测试了这个公式。 Linux 用户可以通过 root 终端输入 apt-get install kmplot 来获取 kmplot,如果这不起作用,请尝试使用常规终端并输入 sudo apt-get install kmplot,如果这不起作用,请观看此 youtube 视频以获取有关一般说明安装Linux程序http://www.youtube.com/watch?v=IkhcwxC0oUg

        所以对线程问题的正确答案是如下所示的 C++ 形式的对称三角形函数声明示例:

        (...)

        int symetrictriangle(float x)
        {
        unsigned int period = 30; // number of increases of x before a new cycle begins
        unsigned int amplitude = 100; // top to bottom value while the bottom value is always zero
        return amplitude * 2 * abs(round(x/period)-(x/period));
        }
        

        (...)

        干杯!

        【讨论】:

        • 其他答案简洁明了,更直接地用“一条线”回答了这个问题。从问题本身来看,很明显 OP 知道三角波是什么,所以不确定为什么这对他们如此敌对。
        • 虽然其他答案都很清楚,但这个答案确实是最容易理解,执行速度最快的,因为它只涉及abs 和基本数学。然而,敌意是不必要的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-16
        • 2014-03-02
        • 1970-01-01
        • 2019-08-13
        • 1970-01-01
        • 2015-08-10
        • 2013-09-17
        相关资源
        最近更新 更多