0

在对整数/双精度变量执行一系列操作后,是否有一种聪明的方法来保留它的符号?通过优雅,我可能更多地关注按位运算或某种功能来保留符号。

这就是我所说的不太优雅的方式:

int myNum = -4;
bool isNegative = myNum < 0 ? true : false;
myNum += 8 / 2 % 4; //some operation
if ((isNegative && myNum > 0) || (!isNegative && myNum < 0))
    myNum *= -1;

编辑:在我的特定场景中的操作只是想改变数字的大小以匹配另一个数字。所以说 myNum 是 -2,matchNum 是 8,我希望 myNum 是 -8。

4

5 回答 5

3

“我遇到的特殊情况是我有一个 2D 坐标系。如果 abs(x) > abs(y) 将 y 的大小更改为匹配 x,反之亦然,abs(x) < abs(y)”

根据您实际尝试执行的方法,这样的方法可能更简单:

int max = Math.Max(Math.Abs(x), Math.Abs(y));    // the larger of the two magnitudes
return (max * Math.Sign(x), max * Math.Sign(y));
于 2013-08-22T05:30:17.723 回答
1

一种更通用的方式(正如人们所说,您需要补偿Math.Sign()返回 0):

int myNum = -4;
int sign = Math.Sign(myNum);
myNum += 8 / 2 % 4; //some operation
myNum = Math.Abs(myNum) * sign;

一种有趣、快速但不可读的整数方法,不受该Math.Sign()问题的影响:

int origNum = -4;
int newNum = origNum + (8 / 2 % 4); //some operation

int signMask = (origNum ^ newNum) >> 31; // flip the sign of newNum if origNum
newNum = (newNum ^ signMask) - signMask; // and newNum have different signs.

或者对于浮点类型,您可以屏蔽符号位,因为它们符合 IEEE 754。如果 JIT 对此很智能,它将产生一些非常有效的 SSE:

double myNum = -4.0;
long sign = GetSign(myNum);
myNum += 8.0 / 2.0 % 4.0; //some operation
myNum = SetSign(myNum, sign);

static long GetSign(double x)
{
    return BitConverter.DoubleToInt64Bits(x) & signMask;
}

static double SetSign(double x, long sign)
{
    return BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(x) & ~signMask | sign);
}

const long signMask = unchecked((long)(1UL << 63));
于 2013-08-22T05:11:09.253 回答
1

您的代码可以缩短为类似

int myNum = -4;
bool isNegative = myNum < 0;
myNum += 8 / 2 % 4; //some operation
myNum *= (isNegative == myNum < 0) ? 1 : -1;

如果您想按位尝试,可以保存最高位并将其用作新符号,但我认为它不会更优雅,但可读性较差。

于 2013-08-22T05:18:17.243 回答
1

这相当简短且易于理解,而且浮点类型的实现将是相同的:

int myValue = -4;
int newValue = some_operation(myValue);

if ( (myValue < 0) ^ (newValue < 0) )
{
    newValue = -newValue;
}
于 2013-08-22T06:39:12.140 回答
0

不知道这是否是最优雅的方式。但是下面的代码可以解决坐标操作。(y/absY) 给了我们符号。absY 是一个量级。

int absX = Math.Abs(x);
int absY = Math.Abs(y);

if(  absX >  absY)
   y = (y/absY)*absX;
else if(  absX <  absY)
   x = (x/absX)*absY;
于 2013-08-22T06:21:19.797 回答