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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:09:34  来源:igfitidea点击:

Why does dividing two int not yield the right value when assigned to double?

c++variablesdoubleinteger-division

提问by Jahoe

How come that in the following snippet

怎么会出现在下面的片段中

int a = 7;
int b = 3;
double c = 0;
c = a / b;

cends up having the value 2, rather than 2.3333, as one would expect. If aand bare doubles, the answer does turn to 2.333. But surely because calready is a double it should have worked with integers?

c正如人们所期望的那样,最终得到的值为 2,而不是 2.3333。如果ab是双打,答案确实变成了 2.333。但肯定是因为c已经是一个 double 它应该与整数一起工作?

So how come int/int=doubledoesn't work?

那怎么int/int=double行不通呢?

回答by Chad La Guardia

This is because you are using the integer division version of operator/, which takes 2 ints and returns an int. In order to use the doubleversion, which returns a double, at least one of the ints must be explicitly casted to a double.

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

c = a/(double)b;

回答by nplatis

Here it is:

这里是:

a) Dividing two ints performs integer division always. So the result of a/bin your case can only be an int.

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

If you want to keep aand bas ints, yet divide them fully, you must cast at least one of them to double: (double)a/bor a/(double)bor (double)a/(double)b.

如果您想保留aand bas ints,但将它们完全分开,则必须至少将它们中的一个转换为 double: (double)a/bor a/(double)bor (double)a/(double)b

b) cis a double, so it can acceptan intvalue on assignement: the intis automatically converted to doubleand 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 doublein 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 / bdouble看不到 a ;一切都是int。所以编译器使用整数除法。只有在得到结果后,它才会考虑如何处理它,并将其转换为double.

回答by Fred Foo

cis a doublevariable, but the value being assigned to it is an intvalue because it results from the division of two ints, which gives you "integer division" (dropping the remainder). So what happens in the line c=a/bis

c是一个double变量,但分配给它的int值是一个值,因为它是两个ints相除的结果,这给你“整数除法”(去掉余数)。所以这条线上发生的事情c=a/b

  1. a/bis evaluated, creating a temporary of type int
  2. the value of the temporary is assigned to cafter conversion to type double.
  1. a/b被评估,创建一个临时类型 int
  2. 临时的值c在转换为 type 后分配给double

The value of a/bis 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 / bcontains 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 / bis 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 resultwhich 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, awill 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 变量是双精度值,结果也将为零。