2016-06-21 31 views
1

无符号短差我有以下:unsigned int的VS在C++

#include <iostream>           

using namespace std;           

float f1(unsigned int x, unsigned int y)      
{                
    float val;            
    val = float(y-x)/(y+x);         
    return val;            
}                

float f2(unsigned short x, unsigned short y)     
{                
    float val;            
    val = float(y-x)/(y+x);         
    return val;            
}                

int main()             
{                
    cout << f1(9612, 9038) << "\n" << f2(9612, 9038) << endl; 
    return 0;             
}                

在输出我从f1f2两个不同的值虽然我期望的输出是相同的,因为功能是相似的。你能解释一下差异的根源吗?

+3

'y'小于'x',所以在'f1'中,'yx'是一个很大的正数,而在'f2'中它是一个小的正数或者一个小的负数(取决于相对你的系统上'short'和'int'的大小) –

+0

我运行了计算,结果是-0.0307774798927614。无符号类型无法处理负值。 – TuukkaX

+0

@TuukkaX:他们当然可以,但你得到2的补充。 – lorro

回答

3

虽然因为两个函数使用一个可能会认为,减法会导致两个值的正数的无符号值,一个是因为整体推广,发生数字类型操作算术评估之前错误的。

cppreference describes arithmetic operator conversions:

如果传递给算术运算器的操作数是积分或无作用域枚举类型,那么之前的任何其他动作(但后左值到右值的转换,如果适用的话),操作数进行积分推广。如果操作数具有数组或函数类型,则应用数组到指针和函数到指针的转换。 ...

积分促销就是这种转换发生。关于这个问题,小整数类型(如炭)的cppreference states the following:

Prvalues可被转换成较大的整数类型的prvalues(如int)。特别是,算术运算符不接受类型均比int作为参数,和积分促销活动左值到右值转换后,如果适用自动应用小。此转换始终保留该值。

因此,如果在数学运算中使用小于整数的类型,则将其转换为整数。这是第二种情况中负值的原因 - 操作数在减法之前转换为int,并产生负值。可能更容易在该特定表达看作((int)y - (int)x),这使得它显而易见的是,它被允许为负。

0

注意y - x为负。它的类型仍然是unsigned short/int。在这种情况下,你倾向于得到2的补码而不是负值,这是不同的,因为sizeof(short)和sizeof(int)对你来说是不同的。

我想你的真正用意是

float f1(unsigned int x, unsigned int y)      
{                
    float val;            
    val = float(float(y) - x)/(y + x);         
    return val;            
} 
+0

,'y-x'的类型是'int'(如果sizeof(int)> sizeof(short)')由于整数促销 –

0

在表达

y-x 

对象xunsigned short类型的y都提升到键入int由于整型提升。你可以把它想象像

(int)y - (int) x 

如果y小于x那么结果将是否定的。

xy是类型unsigned int时,那么结果也有类型unsigned int

0

这是因为y小于xy-x是小于0的,你使用unsigned int和无符号短,所以他们“转换”为正数,根据他们的最大范围内,这是型动物。