C++ 是(1+;sqrt(2))^2=3+;2*sqrt(2)是否满足浮点运算?

C++ 是(1+;sqrt(2))^2=3+;2*sqrt(2)是否满足浮点运算?,c++,math,floating-point,precision,floating-accuracy,C++,Math,Floating Point,Precision,Floating Accuracy,在数学中,恒等式(1+sqrt(2))^2=3+2*sqrt(2)成立。但在浮点(IEEE 754,使用单精度即32位)计算中,情况并非如此,因为sqrt(2)没有二进制的精确表示 那么,使用近似值sqrt(2)是否会为左侧和右侧提供不同的结果?如果是,为什么?将近似值平方是否会显著降低精度 那么,哪一个等价表达式给出了最准确的结果 因为偶数0.1+0.2!=0.3对于有限精度浮点数,不应指望使用如此复杂的等式 由于这些数字被四舍五入到一定数量的二进制小数,如果数字(如0.1)有无限多个二进制数

在数学中,恒等式
(1+sqrt(2))^2=3+2*sqrt(2)
成立。但在浮点(IEEE 754,使用单精度即32位)计算中,情况并非如此,因为
sqrt(2)
没有二进制的精确表示

那么,使用近似值
sqrt(2)
是否会为左侧和右侧提供不同的结果?如果是,为什么?将近似值平方是否会显著降低精度


那么,哪一个等价表达式给出了最准确的结果

因为偶数
0.1+0.2!=0.3
对于有限精度浮点数,不应指望使用如此复杂的等式

由于这些数字被四舍五入到一定数量的二进制小数,如果数字(如0.1)有无限多个二进制数字,它们就不精确。因此,使用这些数字进行计算的结果也不准确,预计与精确计算结果存在微小差异

那么,使用sqrt(2)的近似值是否为左侧和右侧提供了不同的结果?如果是,为什么


从数学上讲,这个等式只适用于这些数字之间的精确关系(它与三角形边的长度有关)。如果以不精确表示的形式添加模糊性,则等式不再成立。平等是一个二元命题,因此问题不再是“哪一方是对的”,而是“这种关系是真的吗?”。答案是,“不,这不再是真的了”

将近似值平方是否会显著降低精度


对两个浮点值的每次操作都可能降低其精度。某些数字的一个非常小的运算子集——那些具有精确位表示的数字——可以保证不会降低精度。

看看好的一面:如果你重新计算该方程以去除
sqrt
s,那么因为你要处理的是大小合理的整数,所以该方程在浮点上是精确的;)

不准确通常与需要小数(除.5和.2的幂)来表示的数字有关



回答你问题的另一部分:否,
sqrt(2)
的表述在双方都是相同的。直到您开始对两侧的同一数字应用(不同)操作时,才会引入错误(和差异):加1与乘2,等等。

比较浮点值时,我发现最好将差异的绝对值与给定公差进行比较。你可以一直相信这一点。

一般来说,双方会给你不同的结果。浮点数学不满足交换性和关联性。涉及到许多因素,包括编译器选项和硬件

对于你的方程,你可能会发现哪一边更准确(我的猜测是相乘的一边),但如果你决定使用不同的值,它通常不会成立,即一边可能对某些值更准确,而另一边对其他值更准确


平方不应该影响到你的情况。

< P>定义C++中的浮点相等比较器的人应该被拍摄:>。许多合理的语言(如SML)没有float的比较运算符。我通常使用以下代码:

template < typename T >
inline bool equals( T x, T y, T precision = std::numeric_limits<T>::epsilon() ) 
{
    return abs( x - y ) <= precision;
}
模板
内联布尔等于(tx,tyy,tprecision=std::numeric_limits::epsilon())
{
返回abs(x-y)通常我使用[(1+sqrt(2))^2]-[3+2*sqrt(2)]<0.00001来测试这种情况下的相等性(当然,在某些情况下我忽略了这种用法)

有更好的办法吗

欢迎评论:)

那么,使用sqrt(2)的近似值是否为左侧和右侧提供了不同的结果?如果是,为什么?对近似值进行平方运算是否会显著降低精度

加法和乘法都有误差近似。乘法是经验的,特别是当它是嵌套的时候

以下不是准确的表述,但有助于理解我的观点:

example of addition:
(float1 * float2 + float3)
float1 * float2 + float3 + mult_approximation + add_approximation

example multiplication
(float1 * (float2 + float3))
(float1 * (float2 + float3 + add_apporiximation)
float1 * (float2 + float3) + add_approximation * float1 + mult_approximation

这是因为像sqrt(x)这样的连续(无限)函数无法在离散(有限)状态机上精确表示。相反,连续函数通过泰勒级数从0到n的展开转换为离散函数,其中n是可以表示的最大数(在本例中为2^32)。因为在计算机上无法求从0到无穷大的和,所以会留下一些剩余误差。可以计算此误差,以便确定离散函数与连续函数的接近程度

有关更多信息和所涉及方程的精确TeX表示:

伙计们,要小心,仅仅依靠绝对差可能会导致问题。它适用于1左右的小数字,小数点足以相差1e-5或你使用的数字。但要考虑较大的数字。它们的数字必须存储在有限的空间(尾数)。并且只存储最重要的数字。这意味着什么?没有空间来存储数字,以允许测量1e-5之类的差异

总而言之,最好同时使用绝对比较和相对比较

bool equal(float a, float b)
{
    if (abs(a - b) < eps)
        return true;
    if (abs(a - b) / max(abs(a), abs(b)) < eps)
        return true;
    return false;
} 
bool相等(浮点a、浮点b)
{
如果(abs(a-b)
在双精度中,
(1+sqrt(2))^2=3+2*sqrt(2)
似乎有效。
请参阅。

令人惊讶的是,如果出于某种原因,您需要非有理数的精确表示(提示:您可能不需要),您可以做一些事情:连分数算术
sqrt(2) = 0x1.6a09e667f3bcd * 2^0
2*sqrt(2) = 0x1.6a09e667f3bcd * 2^1
3 + 2*sqrt(2) = 0x1.7504f333f9de68 * 2^2
3 + 2*sqrt(2) = 0x1.7504f333f9de6 * 2^2
1 + sqrt(2) = 0x1.3504f333f9de68 * 2^1
1 + sqrt(2) = 0x1.3504f333f9de6 * 2^1
(1 + sqrt(2))*(1 + sqrt(2)) = 0x1.7504f333f9de599cacbc97eaa4 * 2^2
(1 + sqrt(2))*(1 + sqrt(2)) = 0x1.7504f333f9de6 * 2^2