Razan Paul
Razan Paul

Reputation: 13838

Boolean to integer conversion

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

Answers (6)

Selmar
Selmar

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 bounds
  • it seems he/she benchmarked in debug

More 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

user1325543
user1325543

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

Mikant
Mikant

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

bit
bit

Reputation: 4487

Use Convert.ToInt32(boolValue)

Upvotes: 1

nvoigt
nvoigt

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

Shaharyar
Shaharyar

Reputation: 12439

int intValue = Convert.ToInt32(boolValue));

Upvotes: 4

Related Questions