Reputation: 13838
Is there a way to covert from bool to integer without a conditional statement (e.g., if-statement)?
int intValue = boolValue ? 1 : 0;
Upvotes: 2
Views: 7555
Reputation: 791
So, yes, with unsafe code you can.
@user1325543 also mentioned this, however there are some problems with the code.
sizeof(bool)
equals 1
and not 4
, so his function is reading out of boundsMore correct code below. I suppose it would be a reasonable idea to assert somewhere that sizeof(bool) == sizeof(byte)
.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
unsafe static public int ToInt32(this bool value)
{
return *(byte*)&value;
}
I also redid his benchmark, and in debug it is about twice as slow. In release, it appears about 20% faster. However, I suspect the real benefit comes from being able to remove the branch in the code that is created from the ?:
operation.
Branch removal was perhaps the original motive behind asking this question?
Edit: this is not super relevant, but in debug mode, when inlining the function by hand, the two approaches seem to run at the same speed.
Upvotes: 1
Reputation: 531
Something to play around with, though I don't recommend it (requires Unsafe code enabled for project):
internal static class Extensions
{
unsafe static public Int32 ToInt32(this bool value)
{
void* b = &value;
return *(Int32*)b;
}
}
Use it like this:
var b = true;
Console.WriteLine($"{b}\t{b.ToInt32()}");
b = false;
Console.WriteLine($"{b}\t{b.ToInt32()}");
Displays:
True 1
False 0
It's slower than the ?: operator, however:
var b = true;
int i = 0;
int iterations = 100_000_000;
Stopwatch sw = Stopwatch.StartNew();
for (int ndx = 0; ndx < iterations; ndx++)
{
i = b ? 1 : 0;
b = !b;
}
sw.Stop();
Console.WriteLine($"?:\t{sw.ElapsedMilliseconds} {i}");
b = true;
sw.Restart();
for (int ndx = 0; ndx < iterations; ndx++)
{
i = b.ToInt32();
b = !b;
}
sw.Stop();
Console.WriteLine($"cast\t{sw.ElapsedMilliseconds} {i}");
My system reports 85ms for the ?: operation, and 180ms for the unsafe method.
Upvotes: 0
Reputation: 326
Despite the fact that nvoigt's answer is perfectly correct I can give you a few more examples JUST FOR FUN
NEVER! NEVER USE THIS CODE! IT IS PROVIDED JUST FOR FUN OR TO RESOLVE A DISPUTE WITH A (GOOD) FRIEND!)
At first method GetHashCode
does the magic (as an implementation detail):
bool b = true;
int i = b.GetHashCode();
If you want some more esoteric approach.. hm.. you're welcome):
bool b = true;
int i = ~(b.ToString()[0] / 2) & 1;
REMEMBER! NEVER!
Upvotes: 4
Reputation: 77285
No, there is not. You may hide this conditional behind additional method calls like Convert.ToInt
, or prefer a different syntax like an actual if
but in the end, somewhere, there will be your conditional.
Upvotes: 2