【问题标题】:Simple program convert int16_t array to uint16_t简单程序将 int16_t 数组转换为 uint16_t
【发布时间】:2017-06-02 06:03:25
【问题描述】:

我已使用 WinFilter 程序计算 C 代码上的 FIR 滤波器,但我遇到了一个问题:

程序只提供 16 位有符号数组,我需要这个向量是一个无符号整数。所以我正在寻找一个简单的解决方案来将数组值重新定位到下一个“值”。

int16_t FIRCoef[Ntap] = {
    -1029,
    -1560,
    -1188,
        0,
     1405,
     2186,
     1718,
        0,
    -2210,
    -3647,
    -3095,
        0,
     5160,
    10947,
    15482,
    17197,
    15482,
    10947,
     5160,
        0,
    -3095,
    -3647,
    -2210,
        0,
     1718,
     2186,
     1405,
        0,
    -1188,
    -1560,
    -1029,
        0
};

uint16_t fir(uint16_t NewSample) {
    static uint16_t x[Ntap]; //input samples
    uint32_t y=0;            //output sample
    int n;

    //shift the old samples
    for(n=Ntap-1; n>0; n--)
       x[n] = x[n-1];

    //Calculate the new output
    x[0] = NewSample;
    for(n=0; n<Ntap; n++)
        y += FIRCoef[n] * x[n]; // calculo da convolucao na amostra
                                // Calculation of the convolution in the sample    
    return y / DCgain;
}

我认为一个解决方案应该是这样的:

uint16_t--------int16_t---------index
0               -32767            1
1               -32766            2
2               -32765            3
...              ...             ...
65535            32767            65535

有什么提示吗?

【问题讨论】:

  • -32768 怎么样,可以表示为int16_t?那不应该是映射到0的值吗?如果“索引”值从 1 开始并运行到 65535,但对应的 uint16_t 值从 0 开始并运行到 65535,那么会跳过哪个 uint16_t 值?
  • return y / DCgain; 这看起来不对。我希望int32_t iy=0; ... return iy / DCgain;
  • 考虑“一个解决方案应该是这样的:0...65535 是偶数到奇数,-32767 ... 32767 是奇数到奇数。这是映射 65,536 @ 987654331@ 转换为 65,535 int16_t。有些东西不见了。
  • fir() 函数对这个问题是否必不可少?我看不出它的哪个方面会影响答案的内容。
  • fir() 函数已经修复。事实上,我实际上并不需要 32 位输出值。

标签: c arrays types uint16


【解决方案1】:

int16_t 的值范围是 -32768 到 32767。您的问题在这一点上不清楚,但您似乎只想将这些值转移到 uint16_t 的范围内,即 0 到 65535。那就是合理,因为这两种类型的可表示值的数量是相同的;这将通过将int16_t 的最小可能值的倒数添加到输入来完成。

当然,魔鬼在细节中。当有符号加法溢出时,会产生未定义的行为。当超出范围的值转换为有符号整数类型时,结果是实现定义的,并且可能是(实现定义的)异常。避免实现定义的行为是可取的,避免未定义的行为是必不可少的;在这种情况下,只需稍加注意即可完成:

uint16_t convert(int16_t in) {
    return (uint16_t) 32768 + (uint16_t) in;
}

这在首先提供uint16_tint16_t 类型的任何符合系统上可靠地做正确的事情,因为转换和加法以1 加uint16_t 的最大值为模。负输入值被转换为 uint16_t 范围上半部分的无符号值,然后加法旋转所有值,将范围上半部分的值带到下半部分。

至于对整个数组执行此操作,如果您只想依赖定义明确的 C 行为(即,如果您想要一个严格符合标准的解决方案),那么您需要制作数据的副本.您可以使用上述函数来填充副本。

【讨论】:

  • 赞成,但这不会将值转移到 [1, 65535] 范围内吗?
  • 不,@DavidBowling,为什么会这样? -32768 转换为 0; +32767 转换为 65535;其他一切都将 1:1 转换为之间的数字。
  • 但不是INT_MIN -32767?
  • @DavidBowling, INT_MIN 是实现定义的并且无关紧要。 -32767 是最大的,但在许多常见平台上,即使是 16 位 ints 的平台,它也更小(更负)。 int16_t(如果提供)是 16 位二进制补码整数类型,没有填充位。由此可见,它的最小值肯定是-32768。总是。
  • 它在那里....我在想最大的允许INT_MIN,即-32767,与最小的16位有符号整数相同,但现在我发现这是错误的。谢谢:)
猜你喜欢
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 2020-11-07
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2020-03-20
  • 2018-09-07
相关资源
最近更新 更多