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+1
  • 如果
    fun()
    floor()
    ,则a2等于a1或a1-1
  • 如果
    fun()
    round()
    ,则a2等于a1
  • 我的问题是,如果我们忽略溢出和下溢

  • 上述结论是否始终成立
  • 如果我无法修复b的精度损失,如何修改代码以确保a2始终等于a1
  • 让我重新措辞

    假设b_-exact是一个精确实数,b是它的浮点表示,a_-exact是func(b_-exact)的结果(如果以无限精度计算),a=func(b)。你想知道| a|u精确-a |有多大,或者| a|u精确-a |/| a|u精确|有多大


    查看第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类型的值。