我有以下内容:
#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;
}
在输出中,我从f1
和f2
得到两个不同的值,尽管我希望输出相同,因为函数是相似的。你能解释一下差异的来源吗?
答案 0 :(得分:3)
虽然两个函数都使用无符号值,但可能会认为减法会导致两个值都为正数,因为在对数值类型的运算符算术求值之前进行了整数提升,因此会出错。
cppreference describes arithmetic operator conversions:
如果传递给算术运算符的操作数是整数或无范围枚举类型,则在执行任何其他操作之前(但在左值到右值转换之后,如果适用),操作数将进行整数提升。如果操作数具有数组或函数类型,则应用数组到指针和函数到指针的转换。 ...
整体促销是进行此转换的地方。关于该主题,cppreference states the following:
小整数类型(例如char)的Prvalues可以转换为更大整数类型(例如int)的prvalues。特别是,算术运算符不接受小于int的类型作为参数,和整数提升会在左值到右值转换后自动应用(如果适用)。此转换始终保留该值。
因此,如果在数学运算中使用小于整数的类型,则将其转换为整数。这是第二种情况下负值的原因 - 操作数在减法之前转换为int,结果产生负值。可能更容易将该特定表达式视为((int)y - (int)x)
,这使得它显然被允许为负数。
答案 1 :(得分: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;
}
答案 2 :(得分:0)
在表达
中y-x
由于整数提升,类型x
的{{1}}和y
被提升为unsigned short
类型。你可以想象它像
int
如果( int )y - ( int ) x
小于y
,那么结果将为负数。
当x
和x
的类型为y
时,结果的类型为unsigned int
。
答案 3 :(得分:0)
这是因为y
小于x
:y-x
小于0,并且您使用unsigned int和unsigned short,因此它们被“转换”为正数,根据他们的最大范围是不同的。