1

I'm trying to encode a byte[] as base[whatever]. It's working in most cases but not all. I can simplify the problem to:

    private void TestDigits()
    {
        ulong number = 15768074845946621;
        ulong l = number;
        uint b = 63;
        List<int> digits = new List<int>();
        while (l >= b)
        {
            digits.Add((int)(l % b));
            l = l / b;
        }
        if (l > 0) { digits.Add((int)l); }

        ulong r = 0;
        for (int i = 0; i < digits.Count; i++)
        {
            ulong pow = (ulong)Math.Pow(b, i);
            r += (ulong)digits[i] * pow;
        }

        if (r != number) throw new InvalidOperationException(String.Format("number:\"{0}\" does not match r:\"{1}\".", number, r));
    }

I think, r should be the same as number? The code works if b is 62 or number is something smaller like 1000. Any idea why, in this case, r is not the same as number?

In most cases, where it's wrong, r is 1 greater than number, so assuming it's a rounding error somewhere, but I cannot spot where.

glboothby
  • 151
  • 8
  • @RobertHarvey - thanks! If I replace Math.Pow with my own version it works! I've been trying to fix that for hours - never thought to look there. – glboothby Aug 09 '23 at 11:27

1 Answers1

1

@RobertHarvey got it! Was Math.Pow not being precise enough.

    private void TestDigits()
    {
        ulong number = 15768074845946621;
        ulong l = number;
        uint b = 62;
        List<int> digits = new List<int>();
        while (l >= b)
        {
            digits.Add((int)(l % b));
            l = l / b;
        }
        if (l > 0) { digits.Add((int)l); }

        ulong r = 0;
        for (int i = 0; i < digits.Count; i++)
        {
            ulong pow = MathPow(b, i);//(ulong)Math.Pow(b, i);
            r += (ulong)digits[i] * pow;
        }

        if (r != number) throw new InvalidOperationException(String.Format("number:\"{0}\" does not match r:\"{1}\".", number, r));
    }
    private ulong MathPow(uint b, int i)
    {
        ulong returnValue = 1;
        for (int j = 0; j < i; j++)
        {
            returnValue *= b;
        }
        return returnValue;
    }
glboothby
  • 151
  • 8
  • 2
    As you're performing integer power ops, why use `Math.Pow` here at all? See https://stackoverflow.com/questions/383587/how-do-you-do-integer-exponentiation-in-c – Dai Aug 09 '23 at 11:34