在没有条件语句的情况下在C#中获取数字的符号

时间:2015-07-22 10:21:32

标签: c# r

出于好奇,是否有办法获得数字的符号,任何类型(但显然是签名类型),而不仅仅是使用某种按位/屏蔽或其他类型的操作的整数? 这是不使用任何条件语句或调用Math.Sign()函数。

提前致谢!

编辑:我认为这是一个误导性的问题。我想到的更像是:"得到Math.Sign()的相同输出,或者,如果x< = 0则简化得到0,否则为#34;

编辑#2 :对于所有要求代码的人,我在发布问题时没有考虑过一些问题,但这是我提出的一个例子,只是为了给出一个可能的应用程序的上下文:

x = (x < 0) ? 0 : x;

将符号转换为变量可能会导致:

x = sign * x; //where sign = 0 for x <= 0, otherwise sign = 1;

目标是获得与上述相同的结果:)

编辑#3 :发现它! :d

// THIS IS NOT MEANT TO BE PLAIN C#!
// Returns 0 if x <= 0, 1 otherwise.
int SignOf(x)
{
    return (1+x-(x+1)%x)/x;
}

感谢大家!

5 个答案:

答案 0 :(得分:2)

  

有没有办法得到一个数字的符号(任何种类,而不仅仅是整数)

不是任何数字类型,不是。对于整数,您可以测试最高位:如果为1,则该数字为负。理论上,您可以使用浮点数执行相同操作,但按位运算符不适用于floatdouble

答案 1 :(得分:0)

要获取符号,您可以避免使用条件运算符,如下面的int32结构的符号扩展中所示。但要获得名称我不认为你可以避免条件运算符

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(0.Sign()); 
        Console.WriteLine(0.SignName());

        Console.WriteLine(12.Sign());
        Console.WriteLine(12.SignName());

        Console.WriteLine((-15).Sign());
        Console.WriteLine((-15).SignName());

        Console.ReadLine();
    }
}

public static class extensions
{
    public static string Sign(this int signedNumber)
    {
        return (signedNumber.ToString("+00;-00").Substring(0, 1));
    }

    public static string SignName(this int signedNumber)
    {
        return (signedNumber.ToString("+00;-00").Substring(0, 1)=="+"?"positive":"negative");
    }
}

答案 2 :(得分:0)

这取决于您定位的数字值类型。

对于签名 Integers C#,大多数计算机系统使用所谓的Ones' complement表示。

这意味着符号存储在值的第一位。

所以你可以提取这样的符号:

Int16 number = -2;
Int16 sign = (number & Int16.MinValue) >> 16;
Boolean isNegative = Convert.ToBoolean(sign);

请注意,到目前为止,我们还没有使用任何条件运算符(显然无论如何)

但是:仍然不知道这个数字是否有迹象。

你问题的逻辑等价物:“我怎么知道,如果我的号码是否定的?”在所有条件

之后,明确要求使用条件运算符

所以你将无法躲闪:

if(isNegative) 
     doThis();
else
     doThat();

答案 3 :(得分:0)

这是一个适用于所有值类型(int、float、double、decimal...等)的“零安全”解决方案:

(value.GetHashCode() >> 31) + 1;

输出:1 = 1, -1 = 0, 0.5 = 1, -0.5 = 0, 0 = 1

它也比 C# 中的 (1+x-(x+1)%x)/x; 便宜大约 10%。此外,如果“value”是一个整数,您可以删除 GetHashCode() 函数调用,在这种情况下,(1+x-(x+1)%x)/x; 的成本高 127%((value >> 31) + 1; 的成本低 56%)。

由于 0 是正数,因此对于正数的结果为 1 而对于 0 的结果为 0 是不合逻辑的。如果您可以参数化 -0,您将得到 0 的输出。

我知道 GetHashCode() 是一个函数调用,但该函数在 C# 语言实现中的内部工作完全是“算术”。基本上 GetHashCode() 函数读取内存部分,将您的浮点类型存储为整数类型:

*((int*)&singleValue);

GetHashCode 函数的工作原理(我能快速找到的最佳来源)- https://social.msdn.microsoft.com/Forums/vstudio/en-US/3c3fde60-1b4a-449f-afdc-fe5bba8fece3/hash-code-of-floats?forum=netfxbcl

如果您希望输出值为 1 且与输入的符号相同,请使用:

((float.GetHashCode() >> 31) * 2) + 1;

上述浮点方法比 System.Math.Sign(float) 便宜大约 39%(System.Math.Sign(float) 大约贵 65%)。 System.Math.Sign(float) 为 float.NaN 抛出异常,((float.NaN.GetHashCode() >> 31) * 2) + 1; 不会并且将返回 -1 而不是崩溃。

或整数:

((int >> 31) * 2) + 1;

上述整数方法比 System.Math.Sign(int) 便宜大约 56%(System.Math.Sign(int) 大约贵 125%)。

答案 4 :(得分:-1)

if x==0,您将有divby0 exception,其中包含您发布的代码:

int SignOf(x) {
    return (1+x-(x+1)%x)/x; }