Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将布尔值转换为字节的最快方法是什么?_C# - Fatal编程技术网

C# 将布尔值转换为字节的最快方法是什么?

C# 将布尔值转换为字节的最快方法是什么?,c#,C#,将布尔值转换为字节的最快方法是什么 我想要这个映射:False=0,True=1 注意:我不想使用任何if语句或其他条件语句。我不希望CPU停止或猜测下一个语句 更新: 对于那些想了解这个问题要点的人。 此示例显示如何从代码中减少两条if语句 byte A = k > 9 ; //If it was possible (k>9) == 0 || 1 c[i * 2] = A * (k + 0x37) - (A - 1) * (k + 0x30); 那么: byte x = valu

将布尔值转换为字节的最快方法是什么

我想要这个映射:False=0,True=1

注意:我不想使用任何
if
语句或其他条件语句。我不希望CPU停止或猜测下一个语句

更新: 对于那些想了解这个问题要点的人。 此示例显示如何从代码中减少两条if语句

byte A = k > 9 ; //If it was possible (k>9) == 0 || 1
c[i * 2] = A * (k + 0x37) - (A - 1) * (k + 0x30);
那么:

byte x = value ? (byte) 1 : (byte) 0;
如果你说的是最有效的方法,那么可能有一些不安全代码的技巧。。。但这真的是你的瓶颈吗

编辑:我刚刚意识到,条件运算符需要对操作数进行这些强制转换,以便使整个表达式成为一个字节

编辑:看到你的问题后,在IMO中有一种更好的优化方法。目前,你将执行不需要任何一种方法的操作。请尝试以下方法:

c[i << 1] = k > 9 ? k + 0x37 : k + 0x30;
请注意,在我的计算机上,这确实为
sum
提供了相同的值,但我根本不确定它是否能保证。我不知道是否有任何保证可以保证
的内存表示形式为true
。。。因此,在某些CLR上,您可能会得到错误的答案

然而,我要指出的是,在我的笔记本电脑上,这个1亿次操作的循环只需要大约300毫秒(这包括增加总和和初始阵列访问,这可能需要大量时间,特别是由于缓存未命中)。。。你真的确定这是瓶颈吗?您希望如何以如此快的速度获取要散列的数据,从而成为问题

编辑:我刚刚添加了另一个循环以查看“基本案例”:

for(int j=0;j
这需要大约一半的时间。。。因此,实际上只有一半的时间花在特定于散列的代码上。你真的,真的确定这是以可读性和潜在正确性为代价进行优化的关键代码吗?

byte x = Convert.ToByte(true);

如果myBool为False,则为0;如果为True,则为1。

使用
unsafe
code此方法速度非常快。通过优化,其速度比条件运算符快约30%

bool input = true;
byte value = *((byte*)(&input)); // 1
//警告!大脑提前编译代码!
静态只读字符[]HexChars={0',1',2',3',4',5',6',7',8',9',A',B',C',D',E',F'};
公共静态字符串ToHex(此字节[]me)
{
如果(me==null)返回null;
int ml=me.Length;
char[]c=新字符[2*ml];
int cp=0;
对于(int i=0;i>4];
}
返回新字符串(c);
}

以下是一个比较三个选项的简单基准:

    Int32 j = 0;
    bool b = true;

    for (int n = 0; n < 5; n++) {
        Stopwatch sw1 = new Stopwatch();
        Stopwatch sw2 = new Stopwatch();
        Stopwatch sw3 = new Stopwatch();
        sw1.Start();
        for (int i = 100 * 1000 * 1000; i > 0; i--)
            unsafe { j = *(int*)(&b); }
        sw1.Stop();

        sw2.Start();
        for (int i = 100 * 1000 * 1000; i > 0; i--)
            j = b ? 1 : 0;
        sw2.Stop();

        sw3.Start();
        for (int i = 100 * 1000 * 1000; i > 0; i--)
            j = Convert.ToInt32(b);
        sw3.Stop();
        Trace.WriteLine("sw1: " + sw1.ElapsedMilliseconds +
            "  sw2:" + sw2.ElapsedMilliseconds + ", +" + 100 * (sw2.ElapsedMilliseconds - sw1.ElapsedMilliseconds) / sw1.ElapsedMilliseconds + "% relative to sw1" +
            "  sw3:" + sw3.ElapsedMilliseconds + ", +" + 100 * (sw3.ElapsedMilliseconds - sw1.ElapsedMilliseconds) / sw1.ElapsedMilliseconds + "% relative to sw1"
            );
    }
结论:

不安全的方法比其他两种方法快25%左右

“if”版本的相对缓慢是由于分支的高成本造成的。 如果Microsoft在编译时进行转换,则可以避免转换成本。

手写IL:

.method private hidebysig static 
    int32 BoolToInt (
        bool b
    ) cil managed noinlining 
{
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldc.i4.0
    IL_0002: cgt.un
    IL_0004: ret
}
而且,它们被一些x86代码所JIT:
(clrjit.dll版本4.7.3131.0)


唯一的问题是,我没有找到在C#中内联IL的简单方法。这个答案是使用dnSpy完成的。

您可以使用此结构执行类似于Chaospanion解决方案的操作,但使用安全代码

[StructLayout(LayoutKind.Explicit)]
struct BoolByte
{
    [FieldOffset(0)]
    public bool flag;
    [FieldOffset(0)]
    public byte num;
}

...

bool someBool = true;
byte num = new BoolByte() { flag = someBool }.num;
我还没有对它进行基准测试,所以我不确定速度如何比较


[编辑]我用与.NET 3.5相当的mono运行了基准测试,它看起来比普通的if检查(在我的macbook pro上)慢约10%。所以忘了这个吧。我怀疑.NET 4+在这方面会有什么不同。

由于.NET Core 2.1,您可以将
bool
重新解释为
字节。这是无分支的,应该非常快,因为它几乎不需要“做”任何事情


从技术上讲,
true
值可以是任何非零的
字节
,但实际上它是
1
。这值得考虑。如果您想要绝对的确定性,您可以寻找一种有效的、无分支的方法,将一个字节转换为非零的
1
,或者将其保留为
0
。(想到两种方法:A)涂抹位,使所有位都是
0
或所有位都是
1
,然后执行
&1
以获得
0
1
。B) 将
0-n
作为
int
,它将是零或负。移动符号位,使其成为最低有效位,从而产生
0
1

是否使用了反射镜?这就是公共静态字节ToByte(bool值){if(!value){return 0;}return 1;}@Vilx-:那么OP不能同时拥有它?1:0实际上对你来说太慢了,那么你真的需要重新检查一下你想做什么。如果该级别的转换每秒发生数千万次(这是它显著影响性能的唯一方式),那么为什么不在ASM或其他版本中编写呢?这是你能显著击败
x的唯一方法?1:0
表示速度。有趣的是,条件“需要优化”中至少有一个(可能有两个)不必要的倍数;-)(但在一天结束的时候……它。只是。没关系。)另一种方法可能是使用switch,它可以作为单个跳转进行优化——不确定是C#还是JIT实现了这一点。另一种方法是查找表。唷!:)@埃米尔:别人指出你找错了人,这是完全正确的,而且经常是有用的。没有人试图不专业地对待你;你有很多人试图给你建议,这样你就可以a)不把时间浪费在毫无意义的优化上,b)更有效地使用这个网站。我们中的许多人都惊讶地看到有人问这个问题,这可能会在我们的评论中出现。但是如果你是从一个否定的角度读的
bool input = true;
byte value = *((byte*)(&input)); // 1
// Warning! Brain-compiled code ahead!
static readonly char[] HexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
public static string ToHex(this byte[] me)
{
    if ( me == null ) return null;
    int ml = me.Length;
    char[] c = new char[2*ml];

    int cp = 0;
    for (int i = 0; i < ml; i++ )
    {
        c[cp++] = HexChars[me[i]&15];
        c[cp++] = HexChars[me[i]>>4];
    }
    return new string(c);
}
    Int32 j = 0;
    bool b = true;

    for (int n = 0; n < 5; n++) {
        Stopwatch sw1 = new Stopwatch();
        Stopwatch sw2 = new Stopwatch();
        Stopwatch sw3 = new Stopwatch();
        sw1.Start();
        for (int i = 100 * 1000 * 1000; i > 0; i--)
            unsafe { j = *(int*)(&b); }
        sw1.Stop();

        sw2.Start();
        for (int i = 100 * 1000 * 1000; i > 0; i--)
            j = b ? 1 : 0;
        sw2.Stop();

        sw3.Start();
        for (int i = 100 * 1000 * 1000; i > 0; i--)
            j = Convert.ToInt32(b);
        sw3.Stop();
        Trace.WriteLine("sw1: " + sw1.ElapsedMilliseconds +
            "  sw2:" + sw2.ElapsedMilliseconds + ", +" + 100 * (sw2.ElapsedMilliseconds - sw1.ElapsedMilliseconds) / sw1.ElapsedMilliseconds + "% relative to sw1" +
            "  sw3:" + sw3.ElapsedMilliseconds + ", +" + 100 * (sw3.ElapsedMilliseconds - sw1.ElapsedMilliseconds) / sw1.ElapsedMilliseconds + "% relative to sw1"
            );
    }
sw1: 172  sw2:218, +26% relative to sw1  sw3:213, +23% relative to sw1
sw1: 168  sw2:211, +25% relative to sw1  sw3:211, +25% relative to sw1
sw1: 167  sw2:212, +26% relative to sw1  sw3:208, +24% relative to sw1
sw1: 167  sw2:211, +26% relative to sw1  sw3:209, +25% relative to sw1
sw1: 167  sw2:212, +26% relative to sw1  sw3:210, +25% relative to sw1
.method private hidebysig static 
    int32 BoolToInt (
        bool b
    ) cil managed noinlining 
{
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldc.i4.0
    IL_0002: cgt.un
    IL_0004: ret
}
test        cl,cl
setne       al
movzx       eax,al
ret
[StructLayout(LayoutKind.Explicit)]
struct BoolByte
{
    [FieldOffset(0)]
    public bool flag;
    [FieldOffset(0)]
    public byte num;
}

...

bool someBool = true;
byte num = new BoolByte() { flag = someBool }.num;