Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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++_Casting - Fatal编程技术网

C++ 复合赋值运算符的类型/类型转换?(例如*=(星等于))

C++ 复合赋值运算符的类型/类型转换?(例如*=(星等于)),c++,casting,C++,Casting,我对示范代码的这一部分感到困惑: float f = 3.01; int i; 案例1:i=f*100;//i==300 案例2:i=f*=100;//i==301 我不知道为什么在第一种情况下小数部分会“丢失”。 我也试过: (double) f * 100 f * 100.0 然后我尝试将volatile和标志添加到gcc,以关闭所有优化。 结果仍然是一样的 有人能给我解释一下为什么第一个案例会这样吗?谢谢。我只能猜测,在第一个示例中,临时结果的精度高于float,结果几乎是301(

我对示范代码的这一部分感到困惑:

float f = 3.01;
int i;
  • 案例1:
    i=f*100;//i==300
  • 案例2:
    i=f*=100;//i==301
我不知道为什么在第一种情况下小数部分会“丢失”。
我也试过:

(double) f * 100
f * 100.0
然后我尝试将volatile和标志添加到gcc,以关闭所有优化。
结果仍然是一样的


有人能给我解释一下为什么第一个案例会这样吗?谢谢。

我只能猜测,在第一个示例中,临时结果的精度高于float,结果几乎是301(例如300.99999999)。在第二个示例中,将结果放入f(浮点)中,并四舍五入到301


我不确定,但这似乎是一个公平的猜测。

第二种情况是f,它是一个浮点数,乘以100,等于301,然后将该值放入int I,没有小数点,因此不会丢失数据。

编译器错误?它在这里工作正常:

问题在于类型转换:

int i = f * 100 ;
相当于

double tmp = f* 100.0;
int i = tmp;
与第二种情况不同的是,tmp是双倍的!是的,有一种情况,双精度是“不太精确的”

为了说明这一点,我编写了以下程序:

int main()
{
    float f = 3.01;
    float mf = f * 100;
    double md = f * 100;

    int if_ = mf;
    int id = md;

    std::cout << f << ' ' << mf << ' ' << md << ' ' << ' ' << (mf - md) << ' ' << if_ << ' ' << id << '\n';
}
Edit2

发现,启用优化
-O2
可以消除问题。这就解释了与IDEONE的区别

下面是另一个代码:

int main()
{
    float f = 3.01;
    float mf = f * 100;
    return mf + (f*100);

    //std::cout << f << ' ' << mf << ' ' << md << ' ' << ' ' << (mf - md) << ' ' << if_ << ' ' << id << '\n';
}
我们只能看到一个到单精度指令的显式转换(
fspts
)。这符合我的猜测,即临时值从
double
计算,而不是从
float
计算

使用
-O2
组装非常简单:

    movl    $602, %eax
终于


如果我们禁用评估优化,我:

也尝试一下:
f=3.01;f=f*100;i=f我认为这应该更加关注这个问题。是的,这就是我所期望的。我不明白为什么临时结果(即使是显式强制转换)的行为方式不一样。我自己刚刚尝试过,我相信在案例一中,编译器将浮点值转换为int,然后再乘以100,结果是300。如果将案例1修改为这一行:I=abs(f*100);它工作,abs返回绝对值。您的输出:--您的程序没有真正显示它应该显示的内容,是吗?;)@cooky451,似乎与依赖无关:gcc 4.6.1和cl 16.00再现了原始错误。你的观点似乎很奇怪,因为表达式f*100是浮动的,而不是双精度的。试试这个:如果它在你的系统上给出“d”或“double”,我们就有理由了。n3242 4.6/1->“float类型的prvalue可以转换为double类型的prvalue。值是不变的。”这基本上意味着编译器可以在这一点上做任何他想做的事情,如果允许纯右值,你甚至不能确定地强制转换。根据标准,我不认为这是一个bug,因为标准允许在任何点进行转换。但允许这样做似乎真的很奇怪。
    movl    $0x4040a3d7, %eax
    movl    %eax, 28(%esp)


    flds    28(%esp)
    flds    LC1
    fmulp   %st, %st(1)
    fstps   24(%esp)
    flds    28(%esp)
    flds    LC1
    fmulp   %st, %st(1)
    fadds   24(%esp)
    fnstcw  14(%esp)
    movw    14(%esp), %ax
    movb    $12, %ah
    movw    %ax, 12(%esp)
    fldcw   12(%esp)
    fistpl  8(%esp)
    fldcw   14(%esp)
    movl    8(%esp), %eax
    movl    $602, %eax