在C/C++中进行数学运算时,我应该对哪些变量进行类型转换?

Jer*_*ten 18 c c++ casting

例如,当我划分两个整数并想要返回一个浮点数时,我迷信地写了这样的东西:

int a = 2, b = 3;
float c = (float)a / (float)b;
Run Code Online (Sandbox Code Playgroud)

如果我不投射ab浮动,它将进行整数除法并返回一个int.

类似地,如果我想将带符号的8位数与无符号8位数相乘,我会在乘法之前将它们转换为带符号的16位数,以免出现溢出:

u8 a = 255;
s8 b = -127;
s16 = (s16)a * (s16)b;
Run Code Online (Sandbox Code Playgroud)

在完全不进行转换或仅转换其中一个变量时,编译器在这些情况下的行为究竟如何?我是否真的需要显式地转换所有变量,或者只是左边的那个变量,还是右边的变量?

Mar*_*ork 26

问题1:浮动部门

int a = 2, b = 3;
float c = static_cast<float>(a) / b;  // need to convert 1 operand to a float
Run Code Online (Sandbox Code Playgroud)

问题2:编译器的工作原理

要记住的五条经验法则:

  • 始终对相同类型的值执行算术运算.
  • 结果类型与操作数相同(促销后)
  • 最小类型算术运算是在int上执行的.
  • ANSCI C(以及C++)使用值保留整数提升.
  • 每个操作都是孤立完成的.

ANSI C规则如下:
这些规则中的大多数也适用于C++,但并非所有类型都得到官方支持(尚未).

  • 如果任一操作数是long double,则另一个操作数转换为long double.
  • 如果任一操作数是double,则另一个操作数转换为double.
  • 如果任一操作数是浮点数,则另一个操作数转换为浮点数.
  • 如果任一操作数是无符号长long,则另一个操作数转换为无符号long long.
  • 如果任一操作数是长的,则另一个操作数转换为long long.
  • 如果任一操作数是无符号长整数,则另一个操作数转换为无符号长整数.
  • 如果任一操作数为long,则另一个操作数转换为long.
  • 如果任一操作数是unsigned int,则另一个操作数转换为unsigned int.
  • 否则两个操作数都转换为int.

溢出

溢出始终是一个问题.注意.结果的类型与输入操作数相同,因此所有操作都可以溢出,所以是的,你需要担心它(尽管语言没有提供任何明确的方法来捕捉这种情况.

作为旁注:
无符号除法不能溢出但签名除法可以.

std::numeric_limits<int>::max() / -1  // No Overflow
std::numeric_limits<int>::min() / -1  // Will Overflow
Run Code Online (Sandbox Code Playgroud)

  • “溢出总是一个问题”。除了一生一次的情况,模运算是您真正想要的。 (2认同)

Ada*_*iss 13

通常,如果操作数的类型不同,编译器会将所有操作数提升为最大或最精确的类型:

If one number is...   And the other is...    The compiler will promote to...
-------------------   -------------------    -------------------------------
char                  int                    int
signed                unsigned               unsigned
char or int           float                  float
float                 double                 double

例子:

char       + int             ==> int
signed int + unsigned char   ==> unsigned int
float      + int             ==> float

但请注意,促销仅在每次中间计算所需时发生,因此:

4.0 + 5/3  =  4.0 + 1 = 5.0

这是因为首先执行整数除法,然后将结果提升为浮点数以进行加法.


Mat*_*ley 5

你可以投出其中一个.然而,哪一个并不重要.

只要类型不匹配,"较小"类型就会自动提升为"较大"类型,浮点数比整数类型"大".


wil*_*ell 2

整数除法:对任一操作数进行强制转换,无需同时对它们进行强制转换。如果两个操作数都是整数,则除法运算是整数除法,否则是浮点除法。

至于溢出问题,不需要显式强制转换,因为编译器会隐式为您执行此操作:

#include <iostream>
#include <limits>

using namespace std;
int main()
{
    signed int a = numeric_limits<signed int>::max();
    unsigned int b = a + 1; // implicit cast, no overflow here
    cout << a << ' ' <<  b << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)