Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当双精度的小数部分加上增量时,最有效的方法是什么;溢出;?_C++_Floating Accuracy - Fatal编程技术网

C++ 当双精度的小数部分加上增量时,最有效的方法是什么;溢出;?

C++ 当双精度的小数部分加上增量时,最有效的方法是什么;溢出;?,c++,floating-accuracy,C++,Floating Accuracy,长话短说,我有一段代码,已有十多年历史,我们和外部客户都在使用它。我们有一个“班次”编号,通过它我们可以移动一个移动窗口。它被设计成一个整数,因为,我们在数据中的不同位置,所以没有分数移动的概念。现在,他们希望能够有一个非整数的移位数。不是插值,只是让程序做一个整数移位,但是当我们通过边界时,让它再移位一点 举个例子可能更有意义。假设我们的班次是10。职位如下: 0、10、20、30、40等 现在,我们希望能够将偏移设置为10.4。因此,我们希望这种转变如下所示: 0,10,20,31,41等

长话短说,我有一段代码,已有十多年历史,我们和外部客户都在使用它。我们有一个“班次”编号,通过它我们可以移动一个移动窗口。它被设计成一个整数,因为,我们在数据中的不同位置,所以没有分数移动的概念。现在,他们希望能够有一个非整数的移位数。不是插值,只是让程序做一个整数移位,但是当我们通过边界时,让它再移位一点

举个例子可能更有意义。假设我们的班次是10。职位如下: 0、10、20、30、40等

现在,我们希望能够将偏移设置为10.4。因此,我们希望这种转变如下所示: 0,10,20,31,41等

而10.5的移位值将显示为0、10、21、31、42等等

基本上,我们把分数位加起来,当它超过小数点时,我们只需再移动一位。当然,正如浮点运算经常发生的那样,我们会遇到精度方面的潜在问题,但我们也希望保持速度。一种简单的方法是在开始时将分数位分离出来,然后继续求和,检查它的值,当它达到1.0时将其递减。这样做的好处是遵循我对操作的想法,但每次迭代都要进行条件检查,而且通常可能会出现累积错误

我还可以看到,在我们必须检查分数位是否超过1.0之前,我们可以预先计算添加分数位的次数(因此,如果分数位是0.5,我们知道我们只需要每隔一次检查一次。或者如果分数位是0.3,我们知道我们只需要每四次左右检查一次)

处理重复求和的常用方法当然是用乘法代替,但在这里,我们不太关心实际的求和,而是预测需要“再移动一次”的帧,以便最终匹配

我们的典型任务涉及到这个类在相对较小的因素组合上进行操作,例如,以96.46875的移位进行不到3000次的迭代。然而,不能保证这个约束仍然有效,所以我被告知要考虑有人将窗口移动一千万次的可能性,我们仍然想知道移动的距离


有什么建议吗?

为什么不使用地板功能呢。在不知道你有什么代码的情况下,这里有一个关于什么工作的猜测

    for (int i=0; i < 3000; i++)
    {
        cout << static_cast<int>(floor(i*shift)) << '\n';
    }
for(int i=0;i<3000;i++)
{

是否可以考虑将
shift
设置为最接近所需值的两倍,并使用以下方法略微增加(仅增加一次):

然后,要计算当前位置,请使用:

result = floor(step * shift);
步骤
的乘积和
移位
中的误差接近1时,这可能会产生一个太大的值。(乘法本身也可能有轻微的舍入误差。)但是,许多步骤不会出现这种情况,如下所示

shift
中的错误最多为1.5 ULP(.5 ULP来自十进制的初始转换,1 ULP来自下一个
)。如果
shift
小于1024,则ULP小于210–52。如果
step
最多为10000000,则误差小于10000000•1.5•210–52,约为3.41•10–6。因此,距离产生错误结果所需的量级还有很长的路要走

如果每次都通过添加
shift
而不是通过新的乘法来累积计算结果,则可能会出现额外的错误。这些错误可能太小而不会导致错误,但应该对它们进行评估


如果达到上述限值,有一些方法可以进一步减小误差。

位移是加法还是乘法?我相信它们是加法。我们处于0、10、21等位置,直到上限(窗口大小)因此,我们从另一边开始。@SeanDuggan:您需要生成完整的窗口列表,还是只生成N次移位的结果?@MatthieuM。实际上,由于基类的编写方式,我需要提供给定帧的当前值。我当前的方法,我上面提到的幼稚方法,覆盖了nextFrame方法od,如果满足或超过1.0,则首先将该值降低到1.0以下,然后添加分数值。另一个函数getShift使用“return intShift_u+”(分数移位>=1.0?1:0)返回当前移位不幸的是,这意味着乘法方法不一定能很好地工作。当期望移位为1.13时,考虑第一百个位置。表达式<代码>楼层(100×1.13)< /> >求值为112,但需要113。这是因为转换“1.13”的结果而发生的。to double是一个略小于1.13的值(使用IEEE-754 64位二进制浮点并四舍五入到最近值)。当然可能会出现舍入错误。假设移位已经是双精度的,因此错误已经存在,并且上述代码不会引入。
result = floor(step * shift);