为什么分配两个int在分配给double时不会产生正确的值?

Jah*_*hoe 94 c++ variables double integer-division

为什么在下面的代码片段中呢?

int a = 7;
int b = 3;
double c = 0;
c = a / b;
Run Code Online (Sandbox Code Playgroud)

c最终得到的值是2,而不是2.3333,正如人们所期望的那样.如果ab双打,答案就变成2.333.但肯定是因为c 已经是双重它本来应该使用整数?

那怎么来int/int=double不行?

Cha*_*dia 146

这是因为你使用整数除法版本operator/,需要2 int秒并返回一个int.为了使用double返回a 的版本,必须将double至少一个ints显式地转换为a double.

c = a/(double)b;
Run Code Online (Sandbox Code Playgroud)

  • 由于问题标记为C++,我更愿意看到static_cast <>而不是C cast. (26认同)
  • 有时你可以通过写'double(b)`来胜过"没有C风格的演员".他们并不总是意识到它是一个转换,因为它看起来与显式构造函数调用相同. (18认同)
  • 就个人而言,我觉得C风格的演员阵容更清晰(大多数其他常见语言的演员都以C风格的方式完成).`static_cast <>`似乎总是啰嗦于我.在原语的情况下,实际上没有让`static_cast <>`和`reinterpret_cast <>`混淆的危险. (15认同)
  • 为了清楚起见,我宁愿将'a`和`b`明确地转换为`double`,但它确实无关紧要. (9认同)
  • @Tux-D:算术演员?在这种情况下,我宁愿避免使用`static_cast`,而是使用C风格的强制转换.在这里使用C++风格的强制转换没有任何好处,它们比C风格的强制转换更加混乱.算术转换正是C风格的强制转换完全合适并且实际上比其他强制转换更合适的上下文. (6认同)

npl*_*tis 12

这里是:

a)除以两个ints总是执行整数除法.所以a/b在你的情况下结果只能是一个int.

如果你想保持abintS,尚未完全分化他们,你必须投他们的双重至少一个:(double)a/ba/(double)b(double)a/(double)b.

b)c是a double,因此它可以接受int关于分配的值:int自动转换为double并分配给c.

c)请记住,在分配时,首先=计算右边的表达式(根据上面的规则(a),而不考虑左边的变量),然后分配给左边的变量(根据(根据( b)上述).我相信这样就完成了.==


Jam*_*nze 9

除了极少数例外(我只能想到一个),C++从表达式本身确定表达式(或子表达式)的整个含义.你用表达式的结果做什么并不重要.在你的情况下,在表达中a / b,没有一个double在眼前; 一切都是int.所以编译器使用整数除法.只有一旦它有结果,它会考虑如何处理它,并将其转换为double.

  • 我能想到的一个例外是在获取指针时选择函数重载 - `&funcname`的值取决于你将它投射到什么类型. (2认同)
  • @Steve Jessop 这也是我能想到的唯一例外。(但考虑到标准的规模和复杂性,我不想发誓我没有错过任何一个。) (2认同)

Alo*_*ave 6

当你除以两个整数时,结果将是一个整数,而不管你将它存储在一个double中.


AnT*_*AnT 6

在 C++ 语言中,子表达式的结果永远不会受到周围上下文的影响(除了一些罕见的例外)。这是该语言认真遵循的原则之一。该表达式c = a / b包含一个独立的子表达式a / b,该子表达式的解释独立于该子表达式之外的任何内容。该语言不关心您稍后会将结果分配给double. a / b是整数除法。别的什么都无所谓。您将在语言规范的许多角落看到遵循这一原则。这就是 C++(和 C)的工作原理。

我上面提到的异常的一个例子是函数重载情况下的函数指针赋值/初始化

void foo(int);
void foo(double);

void (*p)(double) = &foo; // automatically selects `foo(fouble)`
Run Code Online (Sandbox Code Playgroud)

在这种情况下,赋值/初始化的左侧会影响右侧的行为。(此外,对数组的引用初始化可以防止数组类型衰减,这是类似行为的另一个示例。)在所有其他情况下,右侧完全忽略左侧。


Fre*_*Foo 5

c是一个double变量,但赋给它的int值是一个值,因为它是由两个ints 的除法产生的,它给你"整数除法"(删除余数).那么行中发生的事情c=a/b就是

  1. a/b 被评估,创建一个临时类型 int
  2. c转换为type后,临时值被赋值double.

a/b确定的值不参考其上下文(赋值double).


Vic*_*cky 5

/运算符可用于整数除法或浮点除法。你给它两个整数操作数,所以它在做整数除法,然后结果被存储在一个双精度中。