为什么分配给 double 时,两个 int 相除不能得到正确的值?
为什么在下面的代码片段中,
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
最终的值为 2,而不是人们所期望的 2.3333。如果 a
和 b
是双精度数,则答案确实为 2.333。但肯定是因为 c
已经是双精度数了,所以它应该可以处理整数吗?
那么为什么 int/int=double
不起作用呢?
How come that in the following snippet
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
ends up having the value 2, rather than 2.3333, as one would expect. If a
and b
are doubles, the answer does turn to 2.333. But surely because c
already is a double it should have worked with integers?
So how come int/int=double
doesn't work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
这是因为您使用的是
operator/
的整数除法版本,它需要 2 个int
并返回一个int
。为了使用返回double
的double
版本,至少必须将其中一个int
显式转换为双
。This is because you are using the integer division version of
operator/
, which takes 2int
s and returns anint
. In order to use thedouble
version, which returns adouble
, at least one of theint
s must be explicitly casted to adouble
.除了极少数例外(我只能想到一个),C++ 决定了
表达式(或子表达式)的完整含义
本身。您如何处理表达式的结果并不重要。
就您而言,在表达式
a / b
中,没有double
视力;一切都是
int
。所以编译器使用整数除法。只有当它得到结果后,它才会考虑如何处理它,并且
将其转换为
double
。With very few exceptions (I can only think of one), C++ determines the
entire meaning of an expression (or sub-expression) from the expression
itself. What you do with the results of the expression doesn't matter.
In your case, in the expression
a / b
, there's not adouble
insight; everything is
int
. So the compiler uses integer division.Only once it has the result does it consider what to do with it, and
convert it to
double
.如下:
a) 除两个 int 始终执行整数除法。因此,在您的情况下,
a/b
的结果只能是int
。如果您想将
a
和b
保留为int
,但将它们完全分开,则必须将其中至少一个强制转换为 double:<代码>(double)a/b或a/(double)b
或(double)a/(double)b
。b)
c
是一个double
,因此它可以在赋值时接受一个int
值:int
自动转换为double
并分配给c
。c) 请记住,在赋值时,首先计算
=
右侧的表达式(根据上面的规则 (a),并且不考虑=
) 并then 分配给=
左侧的变量(根据上面的 (b))。我相信这就是完整的图景。Here it is:
a) Dividing two
int
s performs integer division always. So the result ofa/b
in your case can only be anint
.If you want to keep
a
andb
asint
s, yet divide them fully, you must cast at least one of them to double:(double)a/b
ora/(double)b
or(double)a/(double)b
.b)
c
is adouble
, so it can accept anint
value on assignement: theint
is automatically converted todouble
and assigned toc
.c) Remember that on assignement, the expression to the right of
=
is computed first (according to rule (a) above, and without regard of the variable to the left of=
) and then assigned to the variable to the left of=
(according to (b) above). I believe this completes the picture.在 C++ 中,子表达式的结果永远不会受到周围上下文的影响(有一些罕见的例外)。这是该语言仔细遵循的原则之一。表达式
c = a / b
由一个独立的子表达式a / b
组成,该子表达式的解释独立于该子表达式之外的任何内容。该语言并不关心您稍后将结果分配给double
。a / b
是整数除法。其他的都无所谓。您将在语言规范的许多角落看到遵循这一原则。这就是 C++(和 C)的工作原理。我上面提到的异常的一个例子是函数重载情况下的函数指针赋值/初始化。
这是一种赋值/初始化的左侧影响右侧行为的上下文。 (此外,对数组的引用初始化可以防止数组类型衰减,这是类似行为的另一个示例。)在所有其他情况下,右侧完全忽略左侧。
In C++, the result of the sub-expression is never affected by the surrounding context (with some rare exceptions). This is one of the principles that the language carefully follows. The expression
c = a / b
consists of an independent sub-expressiona / b
, which is interpreted independently from anything outside that sub-expression. The language does not care that you later will assign the result to adouble
.a / b
is an integer division. Anything else does not matter. You will see this principle followed in many corners of the language specification. That's just how C++ (and C) works.One example of an exception I mentioned above is the function pointer assignment/initialization in situations with function overloading
This is one context where the left-hand side of an assignment/initialization affects the behavior of the right-hand side. (Also, reference-to-array initialization prevents array type decay, which is another example of similar behavior.) In all other cases the right-hand side completely ignores the left-hand side.
当您将两个整数相除时,结果将是一个整数,无论您是否将其存储在双精度型中。
When you divide two integers, the result will be an integer, irrespective of the fact that you store it in a double.
c
是一个double
变量,但分配给它的值是一个int
值,因为它是两个int 除法的结果
s,它给你“整数除法”(去掉余数)。因此,c=a/b
行中发生的情况是a/b
进行求值,创建一个int
类型的临时值(double
类型后分配给c
。a/b
的值是在不参考其上下文的情况下确定的(分配给double
)。c
is adouble
variable, but the value being assigned to it is anint
value because it results from the division of twoint
s, which gives you "integer division" (dropping the remainder). So what happens in the linec=a/b
isa/b
is evaluated, creating a temporary of typeint
c
after conversion to typedouble
.The value of
a/b
is determined without reference to its context (assignment todouble
)./
运算符可用于整数除法或浮点除法。你给它两个整数操作数,所以它进行整数除法,然后结果存储在双精度数中。The
/
operator can be used for integer division or floating point division. You're giving it two integer operands, so it's doing integer division and then the result is being stored in a double.从技术上讲,这取决于语言,但几乎所有语言都以相同的方式对待这个主题。当表达式中的两种数据类型之间存在类型不匹配时,大多数语言会尝试根据一组预定义的规则将
=
一侧的数据转换为匹配另一侧的数据。当两个相同类型的数字(整数、双精度数等)相除时,结果将始终是相同的类型(因此“int/int”将始终生成 int)。
在这种情况下你有
double var = 整数结果
计算后将整数结果转换为双精度型,在这种情况下小数数据已经丢失。 (大多数语言都会执行此转换以防止类型不准确,而不会引发异常或错误)。
如果您想将结果保持为双倍,您将需要创造一种情况:
double var = double result
最简单的方法是强制等式右侧的表达式转换为 double:
c = a/(double)b
整数和双精度数之间的除法将导致将整数转换为双精度数(请注意,在进行数学计算时,编译器通常会“向上转换”为最具体的数据类型,这是为了防止数据丢失)。
向上转换后,
a
将最终成为双精度数,现在您可以在两个双精度数之间进行除法。这将创建所需的划分和分配。再次,请注意,这是特定于语言的(甚至可以是特定于编译器的),但是几乎所有语言(当然是我能立即想到的所有语言)都以相同的方式对待这个示例。
This is technically a language-dependent, but almost all languages treat this subject the same. When there is a type mismatch between two data types in an expression, most languages will try to cast the data on one side of the
=
to match the data on the other side according to a set of predefined rules.When dividing two numbers of the same type (integers, doubles, etc.) the result will always be of the same type (so 'int/int' will always result in int).
In this case you have
double var = integer result
which casts the integer result to a double after the calculation in which case the fractional data is already lost. (most languages will do this casting to prevent type inaccuracies without raising an exception or error).
If you'd like to keep the result as a double you're going to want to create a situation where you have
double var = double result
The easiest way to do that is to force the expression on the right side of an equation to cast to double:
c = a/(double)b
Division between an integer and a double will result in casting the integer to the double (note that when doing maths, the compiler will often "upcast" to the most specific data type this is to prevent data loss).
After the upcast,
a
will wind up as a double and now you have division between two doubles. This will create the desired division and assignment.AGAIN, please note that this is language specific (and can even be compiler specific), however almost all languages (certainly all the ones I can think of off the top of my head) treat this example identically.
出于与上述相同的原因,您必须将“a”或“b”之一转换为双精度类型。另一种方法是使用:
分子(隐式)转换为双精度型,因为我们向其添加了双精度型,即 0.0。
For the same reasons above, you'll have to convert one of 'a' or 'b' to a double type. Another way of doing it is to use:
The numerator is (implicitly) converted to a double because we have added a double to it, namely 0.0.
重要的是计算元素之一是 float-double 类型。然后,要获得双重结果,您需要如下所示转换此元素:
或
c = a / static_cast(b);
或者您可以直接创建它::
请注意,计算的元素之一必须具有“.0”,以指示 float-double 类型除以整数。否则,尽管 c 变量是双精度型,但结果也将为零(整数)。
The important thing is one of the elements of calculation be a float-double type. Then to get a double result you need to cast this element like shown below:
or
c = a / static_cast(b);
Or you can create it directly::
Note that one of elements of calculation must have the '.0' to indicate a division of a float-double type by an integer. Otherwise, despite the c variable be a double, the result will be zero too (an integer).