简体   繁体   English

管理C ++单精度和双精度混合计算的规则是什么?

[英]What are the rules governing C++ single and double precision mixed calculations?

For example, these variables: 例如,这些变量:

result (double)
a (double)
b (float)
c (float)
d (double)

A simple calculation: 一个简单的计算:

result = a * (b + c) * d

How and when are the types converted and how do I figure out what precision each calculation is performed at? 如何以及何时转换类型以及如何计算每次计算的精度?

All operations are done on objects of the same type (assuming normal arithmetic operations). 所有操作都在相同类型的对象上完成(假设是正常的算术运算)。

If you write a program that uses different types then the compiler will auto upgrade ONE parameter so that they are both the same. 如果编写使用不同类型的程序,编译器将自动升级ONE参数,使它们都相同。

In this situations floats will be upgraded to doubles: 在这种情况下,浮动将升级为双打:

result      = a * (b + c) * d

float  tmp1 = b + c;            // Plus operation done on floats.
                                // So the result is a float

double tmp2 = a * (double)tmp1; // Multiplication done on double (as `a` is double)
                                // so tmp1 will be up converted to a double.

double tmp3 = tmp2 * d;         // Multiplication done on doubles.
                                // So result is a double

result      = tmp3;             // No conversion as tmp3 is same type as result.

If you have: 如果你有:

float f;
double d;

...then an arithmetic expression like f * d will promote both operands to the larger type, which in this case is double . ...然后像f * d这样的算术表达式会将两个操作数提升为更大的类型,在本例中为double

So, the expression a * (b + c) * d evaluates to a double , and is then stored in result , which is also a double . 因此,表达式a * (b + c) * d计算结果为double ,然后存储在resultresult也是double This type promotion is done in order to avoid accidental precision loss. 这种类型的促销是为了避免意外的精确损失。

For further information, read this article about the usual arithmetic conversions . 有关详细信息,请阅读有关通常的算术转换的文章。

You have parenthesis delimiting the float adition. 您有括号分隔浮动adition。 So it would do b + c as float + float. 所以它会做b + c作为float + float。 Convert this to double for keeping largest precision, then multiply the double values. 将其转换为double以保持最大精度,然后将double值相乘。

However in such case where you want control over conversions, and not guessing: use static_cast<>() ; 但是,在这种情况下,您需要控制转换,而不是猜测:使用static_cast<>() ;

Following order of operations, each sub-expression is converted to the type of it's (not sure of the term here, dominant perhaps?) type. 按照操作顺序,每个子表达式都转换为它的类型(不确定这里的术语,可能是主导?)类型。 double is dominant over float, so: double优于float,因此:

(b + c) // this is evaluated as a float, since both b and c are floats
a * (b + c) // this is evaluated as a double, since a is a double
a * (b + c) * d // this is evaluated as a double, since both "a * (b + c)" and d are doubles

You have to differentiate between type conversion and value conversion. 您必须区分类型转换和值转换。 The C++ standard (C as well) allows floating-point calculations to be done at extended precision. C ++标准(C也是如此)允许以扩展精度完成浮点计算。

"The values of the floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby." “浮动操作数的值和浮动表达式的结果可以用比类型所需的精度和范围更高的精度和范围来表示;类型不会因此而改变。”

As types, b + c is an addition of two float(s). 作为类型,b + c是两个浮点数的加法。 The result is a float. 结果是浮动。 The result is then type promoted to a double and the two multiplications are done as doubles with a result of double. 然后将结果类型提升为double,并将两次乘法作为double的双倍结果进行。

However, an implementation is allowed to do all the calculations, including b + c, using doubles (or higher precision). 但是,允许实现使用双精度(或更高精度)执行所有计算,包括b + c。 Indeed, I tried it out using Visual C++ and it did all the calculations using the 80-bit floating-point stack available on x86. 实际上,我使用Visual C ++进行了尝试,并使用x86上提供的80位浮点堆栈进行了所有计算。

The floats will be upconverted to doubles. 花车将被翻转为双打。 Explicitly cast the values. 明确地施放值。

ie if you want double as your result you would write: 即如果你想要双倍的结果,你会写:

result = a * double( b + c ) * d;

It is ALWAYS worth being explicit. 它总是值得明确的。 It gets round misunderstandings like this and it is INSTANTLY obvious to anyone trying to use your code exactly what you mean. 它会产生这样的误解,对于任何试图完全按照你的意思使用你的代码的人来说,它是显而易见的。

In your example, all the float types are type-promoted to double when the right-side formula is evaluated. 在您的示例中,当评估右侧公式时,所有float类型都被类型提升为double

As for how they're converted: What I've read regarding floating point operations is that most contemporary hardware perform FP operations using extended-precision (80 bit) long doubles in special hardware registers (at least that's what I remember about modern Intel x86/x87 processors). 关于它们如何转换:我读到的关于浮点运算的是大多数现代硬件在特殊硬件寄存器中使用扩展精度(80位)长双精度执行FP操作(至少这是我记得的现代Intel x86) / x87处理器)。 As I understand it, float and double are type-promoted IN HARDWARE via special FP instructions (someone correct me if I'm wrong). 据我了解, floatdouble是通过特殊的FP指令在类型中提升的硬件(如果我错了,有人会纠正我)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM