C++ 为什么在分配给 double 时除以两个 int 不会产生正确的值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7571326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does dividing two int not yield the right value when assigned to double?
提问by Jahoe
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?
c
正如人们所期望的那样,最终得到的值为 2,而不是 2.3333。如果a
和b
是双打,答案确实变成了 2.333。但肯定是因为c
已经是一个 double 它应该与整数一起工作?
So how come int/int=double
doesn't work?
那怎么int/int=double
行不通呢?
回答by Chad La Guardia
This is because you are using the integer division version of operator/
, which takes 2 int
s and returns an int
. In order to use the double
version, which returns a double
, at least one of the int
s must be explicitly casted to a double
.
这是因为您使用的是 的整数除法版本operator/
,它需要 2int
秒并返回一个int
。为了使用double
返回 a的版本,必须double
至少将int
s 中的一个显式转换为 a double
。
c = a/(double)b;
回答by nplatis
Here it is:
这里是:
a) Dividing two int
s performs integer division always. So the result of a/b
in your case can only be an int
.
a) 除以两个int
s 总是执行整数除法。所以a/b
在你的情况下的结果只能是int
.
If you want to keep a
and b
as int
s, yet divide them fully, you must cast at least one of them to double: (double)a/b
or a/(double)b
or (double)a/(double)b
.
如果您想保留a
and b
as int
s,但将它们完全分开,则必须至少将它们中的一个转换为 double: (double)a/b
or a/(double)b
or (double)a/(double)b
。
b) c
is a double
, so it can acceptan int
value on assignement: the int
is automatically converted to double
and assigned to c
.
b)c
是 a double
,因此它可以接受int
赋值时的值: theint
会自动转换为double
并赋值给c
。
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 thenassigned to the variable to the left of =
(according to (b) above). I believe this completes the picture.
c) 请记住,在赋值时,首先=
计算右边的表达式(根据上面的规则(a),不考虑左边的变量),然后分配给左边的变量(根据( b) 以上)。我相信这完成了图片。=
=
回答by James Kanze
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 a double
in
sight; 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
.
除了极少数例外(我只能想到一个),C++ 从表达式本身确定表达式(或子表达式)的全部含义。你对表达式的结果做什么并不重要。在您的情况下,在表达式中a / b
,double
看不到 a ;一切都是int
。所以编译器使用整数除法。只有在得到结果后,它才会考虑如何处理它,并将其转换为double
.
回答by Fred Foo
c
is a double
variable, but the value being assigned to it is an int
value because it results from the division of two int
s, which gives you "integer division" (dropping the remainder). So what happens in the line c=a/b
is
c
是一个double
变量,但分配给它的int
值是一个值,因为它是两个int
s相除的结果,这给你“整数除法”(去掉余数)。所以这条线上发生的事情c=a/b
是
a/b
is evaluated, creating a temporary of typeint
- the value of the temporary is assigned to
c
after conversion to typedouble
.
a/b
被评估,创建一个临时类型int
- 临时的值
c
在转换为 type 后分配给double
。
The value of a/b
is determined without reference to its context (assignment to double
).
的值a/b
是在不参考其上下文的情况下确定的(分配给double
)。
回答by Alok Save
When you divide two integers, the result will be an integer, irrespective of the fact that you store it in a double.
当您将两个整数相除时,结果将是一个整数,而不管您是否将它存储在 double 中。
回答by AnT
In C++ language the result of the subexpresison 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
contains of an independent subexpression a / b
, which is interpreted independently from anything outside that subexpression. The language does not care that you later will assign the result to a double
. 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 juts how C++ (and C) works.
在 C++ 语言中,子表达式的结果永远不会受到周围上下文的影响(除了一些罕见的例外)。这是该语言认真遵循的原则之一。该表达式c = a / b
包含一个独立的子表达式a / b
,该子表达式的解释独立于该子表达式之外的任何内容。该语言不关心您稍后会将结果分配给double
. a / b
是整数除法。别的什么都无所谓。您将在语言规范的许多角落看到遵循这一原则。这就是 C++(和 C)的工作原理。
One example of an exception I mentioned above is the function pointer assignment/initialization in situations with function overloading
我上面提到的异常的一个例子是函数重载情况下的函数指针赋值/初始化
void foo(int);
void foo(double);
void (*p)(double) = &foo; // automatically selects `foo(fouble)`
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.
在这种情况下,赋值/初始化的左侧会影响右侧的行为。(此外,对数组的引用初始化可防止数组类型衰减,这是类似行为的另一个示例。)在所有其他情况下,右侧完全忽略左侧。
回答by Vicky
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.
该/
运算符可用于整数除法或浮点除法。你给它两个整数操作数,所以它在做整数除法,然后结果被存储在一个双精度中。
回答by matthewdunnam
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).
当两个相同类型的数(整数、双精度数等)相除时,结果将始终是相同类型(因此 'int/int' 将始终产生 int)。
In this case you have
double var = integer result
which casts the integer result to a double after the calculationin which case the fractional data is already lost. (most languages will do this casting to prevent type inaccuracies without raising an exception or error).
在这种情况下,您可以
在计算后将double var = integer result
整数结果转换为双精度值,在这种情况下小数数据已经丢失。(大多数语言都会执行此转换以防止类型不准确,而不会引发异常或错误)。
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
如果您想将结果保留为双倍,您将需要创建一种情况,您有
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
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.
upcast 之后,a
将作为双打结束,现在您可以在两个双打之间进行划分。这将创建所需的划分和分配。
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.
再次请注意,这是特定于语言的(甚至可以是特定于编译器的),但是几乎所有语言(当然是我能想到的所有语言)都相同地对待这个例子。
回答by TheArquitect
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:
重要的是计算的元素之一是 float-double 类型。然后要获得双重结果,您需要像下图所示投射此元素:
c = static_cast<double>(a) / b;
or c = a / static_cast(b);
或 c = a / static_cast(b);
Or you can create it directly::
或者你可以直接创建它::
c = 7.0 / 3;
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.
请注意,计算元素之一必须具有 '.0' 以指示 float-double 类型除以整数。否则,尽管 c 变量是双精度值,结果也将为零。