ceil、floor和round功能放大精度损失问题的严重程度如何?如何消除这种影响? 以前我曾发布过一个关于C++函数的问题,即代码> > CELL()/,代码> >()>代码> >代码>循环()/。该问题的链接如下
从我收到的两个答案中,我了解到这些函数本身是精确的,但它们会放大现有的精度损失问题 我想知道这些问题能放大到多大程度。具体来说,考虑以下内容:ceil、floor和round功能放大精度损失问题的严重程度如何?如何消除这种影响? 以前我曾发布过一个关于C++函数的问题,即代码> > CELL()/,代码> >()>代码> >代码>循环()/。该问题的链接如下,c++,C++,从我收到的两个答案中,我了解到这些函数本身是精确的,但它们会放大现有的精度损失问题 我想知道这些问题能放大到多大程度。具体来说,考虑以下内容: a = fun(b); 这里,a是一个整型值(int,long,long,等等),b是一个浮点型值(float,double),而fun()是ceil(),floor()和round()中的一种。请注意,在下面的所有讨论中,我假设没有溢出或下溢问题 注意,这里,我假设b是通过可能导致精度损失的其他操作获得的。例如,假设我希望b等于1.1+3.9=5,但
a = fun(b);
这里,a
是一个整型值(int
,long
,long
,等等),b
是一个浮点型值(float
,double
),而fun()
是ceil()
,floor()
和round()
中的一种。请注意,在下面的所有讨论中,我假设没有溢出或下溢问题
注意,这里,我假设b是通过可能导致精度损失的其他操作获得的。例如,假设我希望b等于1.1+3.9=5,但是,由于1.1和3.9无法表示,因此b不会以5结束
我想知道这些问题会在多大程度上影响a的价值。具体而言,a的正确值(即,如果b没有精度损失)与实际获得的值(即,如果存在潜在精度损失)相差多少。假设我们将正确值表示为a1,实际值表示为a2。在我看来,在任何情况下,以下结论都必须成立
fun()
是ceil()
,则a2等于a1或a1+1fun()
为floor()
,则a2等于a1或a1-1fun()
是round()
,则a2等于a1查看第7.4节中IEEE浮点表示法产生的最大绝对误差和最大相对误差的表格。首先,您假设您的误差
b
很小。如果b
中的错误大于1.0,则您的任何结论都不成立。但在实践中,b
中的误差可能很小,这是一个合理的假设
然而,结论3在所有情况下都是错误的。正确的结果是a2等于a1-1,或a1+1,或a1。假设b的正确值为3.49999,实际值为3.50001,则当正确结果为3时,round
将给出4。反之亦然,如果正确值为3.50001,实际值为3.49999,则当正确结果为4时,round
将给出3
至于问题2,没有简单的答案。而且不可能笼统地回答这个问题,所以需要一些关于你实际问题的细节。听起来,当你需要精确的结果时,你正试图使用不精确的算术。也许你需要切换到某种类型的多精度算法,例如,有几个库在这里。如果你问C++,不要包括C标签——反之亦然。请看更新后的问题。我知道fun()会产生精确的值。我关心的是,如果b不精确,那么这个精度在多大程度上可以被fun()放大。还有一个问题,假设我正在对double/float精度值执行一系列操作。所有的初始值、中间结果和最终结果都是可表示的,那么我能保证得到精确的结果吗?例如,考虑代码A= B*C+D/E。假设b,c,d,e的值是精确的,b*c,d/e和b*c+d/e的精确值都是可表示的,我能保证a是精确的吗?是的,我相信是这样。IEEE754标准保证任何操作的结果都是最准确的。因此,如果结果是可精确表示的,那么这就是您应该得到的结果。需要注意的是,我不确定库函数
sin
、cos
、sqrt
等的保证是什么,它们可能会返回不准确的结果。你确定中间结果是可表示的吗?如果是这样的话,这是一个非常不寻常的情况。我只是想确认你是否意识到,即使是十分之一这样的简单分数也不能表示为浮点数。事实上,我相信我就是这样。基本上,我的代码类似于int_1=int_2*int_3*log2(int_4)+int_5*(log2(int_4)+ceil(log2(int_3));这里log2和ceil返回双值。如果精确计算,log2(int_4)应该等于一个整数(我通过比较(int)log2(int_4),(int)(ceil(log2(int_4))和(int)(floor(log2(int_4))检查了这一点),它们共享相同的值)。似乎我对ceil(log2(int_3))的精度做不了太多,所以我不得不假设它是精确的。剩下的中间结果似乎是可以表示的。这里int_1到int_5都是int类型的值。