x raised to the power 0 does not evaluate to 1

995 views Asked by At

I created a class for doing unit conversions, specifically bytes to kilobytes, megabytes, gigabytes, etc. I have an enum with B through PB, but for some reason 1024^0 does not return 1 and it's not correctly converting from bytes to bytes or bytes to kilobytes, etc.

Here's my class:

public static class UnitConversion
{
    /// <summary>
    /// 1024^n
    /// </summary>
    public enum ByteConversionConstant
    {
        B = 0,
        KB = 1,
        MB = 2,
        GB = 3,
        TB = 4,
        PB = 5
    }

    public static string GetValueFromBytes(long bytes,
                            ByteConversionConstant constant)
    {
        int n = (int)constant;
        long divisor = 1024^n;
        return (bytes / divisor).ToString() + 
               Enum.GetName(typeof(ByteConversionConstant), constant);
    }
}

The following statement should return exactly the same value as fileInfo.Length, but since 1024^0 isn't returning 1, it's showing the number of kilobytes. Note, I had the GetValueFromBytes method all in one line, but I separated it out to see what could be causing the miscalculation.

UnitConversion.GetValueFromBytes(fileInfo.Length, 
                                 UnitConversion.ByteConversionConstant.B)

I'm not sure if it's an issue with casting the enum to an int or if something gets lost when raising an int to an int and assigning it to a long, but this is strange behavior.

5

There are 5 answers

1
Jon Skeet On BEST ANSWER

You're using the ^ operator, which is not an exponentiation operator. It's exclusive-OR.

Use Math.Pow for exponentiation - or better, just use bit-shifting in this case:

long divided = bytes >> (n * 10);
return divided.ToString() + ...;

Alternatively, you could change your enum values to the actual values to divide by:

public enum ByteConversionConstant : long
{
    B = 1L << 0,
    KB = 1L << 10,
    MB = 1L << 20,
    GB = 1L << 30,
    TB = 1L << 40,
    PB = 1L << 50
}

Then:

long divided = n / (long) constant;
1
Bill Morrison On

You should be using Math.Pow().

^ is not used for powers, but for bitwise operations instead (see http://msdn.microsoft.com/en-us/library/zkacc7k1.aspx for details).

3
Daniel Hilgarth On

^ is the XOR operator. What you want to achieve is done via Math.Pow.

0
Pierre-Luc Pineault On

^ is a bitwise operator, you are currently doing '1024 XOR 0'.

I think you are looking for Math.Pow(1024, n);, which is '1024 raised to the power 0'

0
Dave Zych On

The ^ operator does not raise the number to that power, it is the Bitwise XOR operator.

You want Math.Pow

long divisor = Math.Pow(1024, n);