Столкнулись на работе с интересным поведением Convert.ToInt32. Почти всегда работает предсказуемо, кроме граничных случаев (оканчивающихся на ".5").

Обзор документации дал вполне точное (но при этом достаточно странное) объяснение:
If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.

Т.е. неискушенные умы могут подумать, что это ошибка. Вот код соответствующий «волшебному» методу:
    public static int ToInt32(double value)
    {
      if (value >= 0.0)
      {
        if (value < 2147483647.5)
        {
          int num1 = (int) value;
          double num2 = value - (double) num1;
          if (num2 > 0.5 || num2 == 0.5 && <b>(num1 & 1) != 0</b>)
            ++num1;
          return num1;
        }
      }
      else if (value >= -2147483648.5)
      {
        int num1 = (int) value;
        double num2 = value - (double) num1;
        if (num2 < -0.5 || num2 == -0.5 <b>&& (num1 & 1) != 0</b>)
          --num1;
        return num1;
      }
      throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
    }

Можно заметить, что во внутреннем условии есть проверка на четность, которая и вносит «магические» коррективы. Для чего это необходимо, для меня осталось загадкой.

Покопавшись в интернете есть статьи, в которых столкнулись с похожей проблемой, где, как вариант, предлагают использовать операции приведения. Мы же решили сделать свою реализацию, убрав условия проверки:

    public static int ToInt32(double value)
    {
      if (value >= 0.0)
      {
        if (value < 2147483647.5)
        {
          int num1 = (int) value;
          double num2 = value - (double) num1;
          if (num2 > 0.5 || num2 == 0.5)
            ++num1;
          return num1;
        }
      }
      else if (value >= -2147483648.5)
      {
        int num1 = (int) value;
        double num2 = value - (double) num1;
        if (num2 < -0.5 || num2 == -0.5)
          --num1;
        return num1;
      }
      throw new OurOverflowException('Int32 overflow error message');
    }

В комментариях можно оставить предположения, для чего добавлена «магия» в этот, с виду предсказуемый, метод.