在固定点类型

时间:2016-02-25 20:20:57

标签: c++ algorithm theory modulus fixed-point

所以目前我正在帮助开发一种编程语言,我们已经达到了这样的程度,我们必须使用C ++作为我们的主干语言来实现定点类型。我能够想到如何加,减,乘,除,但是我正在绘制一个空白,以便如何实现模数和指数。我觉得我已经接近计算指数,所以我将把这个问题集中在模数上。

目前我所做的是我接受一个字符串文字并跟踪基数的点并找到它与字符串末尾的距离,这给了我缩放因子。在那之后我们保留整个大整数,这应该被约束为固定类型(除非出现分裂...或可能的模数等情况,此时我们将基数的小数侧增加到至少一半的大小整数部分)。我已经实现了通过乘以10的因子(我希望基数10的精度而不是基数2的速度)来获取基数左边和基数右边的值的方法来获取基数将坐下。我已经谷歌搜索如何在定点类型上实现模数,但无济于事。

我似乎无法弄清楚如何实施它。有没有办法实现这个?人们知道广义算法吗?有什么能指引我正确的方向吗?请记住,我的目标是准确性。速度也很好,但主要指令是准确性。

为了澄清,我们将要操作的硬件是一般化的。至于我想要的定义......这就是我在这里的原因。我不知道自己想要什么,我想知道一些例子和不同的选择。我真的只是想了解这一点。

实施例

说我有一个fixed8x8,我推出2%1.2(2也可能是2.0),结果应该回到0.8。对于扩大右侧的大小以补偿准确性,有什么好的规则?

1 个答案:

答案 0 :(得分:3)

修正1.2%2 == 1.2,然后忽略小数,例如这与12%20 == 12

相同

如果真的不需要速度,你可以使用减法来计算它。例如。对于任何A%M,只需从A中减去M直到A <1。 M,M!= 0(无限循环!)。这将提供相同的结果,1.2,因为当表示为定点时,减法确实不受小数点的影响。

如果速度很重要,并且您没有可以忽略小数的乘法例程(最多赢得),您可能需要构建它们,因为在8x8时您没有足够的空间将整个值移到左侧(对于某些操作,我在PIC 16F库中实现了24x8定点寄存器,以便在16x8定点上执行计算时具有更高的精度。)

详细说明使用乘法进行更快的算术运算,以及需要可忽略小数的乘法程序的原因,

首先,我们使用这个伪C ++代码分析较慢的减法方法:

auto answer = A;
while(answer >= M)
  answer -= M;
// now, your answer is in answer

但如果我们事先知道需要多少次迭代,我们就可以:

auto answer = A - M * number_of_iterations;

当然,我们不知道这一点,因此我们的目标是减少我们需要的迭代次数。这可以通过反向因子分解来实现 - 给定数字M,找到你可以将它乘以10(左边一个数字)并且它仍然小于A的次数,例如,如果A是1023.32且M是4.1,则可以将M乘以10两次,得到M * 10 * 10 = 410.从A减去A直到A <1。 M * 10 * 10,离开A&#39; = 203.32,并继续重复,直到A的工作副本小于M.这种转向方法通常将O(N)操作转换为O(log(N))操作如果你不为计算增加太多的开销(在我的PIC 16F实现中,我必须小心,因为芯片只有384字节的总内存,所以不用说,它比它可能有的慢)过)。

我主要是在base-2中完成我的工作,但同样的想法也转换为base-10,所以这样的东西应该大大减少迭代次数,特别是对于较大的项目(这可以根据你的需要进行调整)内部表示,所以你可以使用数字移位而不是每一步的乘法):

auto currentA = A;
while(currentA >= M){
  auto scaledM = M;
  while(scaledM*10 < currentA)
    scaledM *= 10;
  // this second loop prevents recomputing scaledM where
  // currentA > n*scaledM for some n < 10; not needed in base-2
  while(currentA > scaledM)
    currentA -= scaledM;
}

当完成时,currentA将包含你的模数。