Как определить длину числа
Застрял на задании в определении длины числа типа int. Проблема в том, что код считает длины всех чисел в тесте (+ и -), кроме int.MinValue, в отладчике возвращает NaN. Не могу понять почему так происходит, помогите пожалуйста.
public static byte GetLengthWithCascadedIfElse(int number)
{
if (number < 0)
{
return (byte)Math.Floor(Math.Log10((int)(-number)) + 1);
}
else if (number == 0)
{
return 1;
}
else
{
return (byte)Math.Floor(Math.Log10((int)number) + 1);
}
}
Ответы (5 шт):
Можно просто в лоб посчитать число разрядов:
public int Digits(int num)
{
if (num == 0)
return 1;
var result = 0;
while(num > 0)
{
num = num / 10;
result++;
}
return result;
}
Ваш подход тоже рабочий:
public int Digits(int number)
{
if (number == 0)
return 1;
var num = Math.Abs(number);
var result = Math.Log10(num) + 1;
return (int) result;
}
Набор юнит-тестов:
[Test]
[TestCase(0, 1)]
[TestCase(1, 1)]
[TestCase(2, 1)]
[TestCase(3, 1)]
[TestCase(9, 1)]
[TestCase(10, 2)]
[TestCase(42, 2)]
[TestCase(99, 2)]
[TestCase(100, 3)]
[TestCase(123, 3)]
[TestCase(1979, 4)]
[TestCase(-2147483648, 10)]
[TestCase(2147483647, 10)]
public void SolutionTests(int num, int expected)
{
var actual = new Solution().Digits(num);
Assert.That(actual, Is.EqualTo(expected));
}
Всё просто: int.MinValue равен -2147483648, а MaxValue — 2147483647, т.е. -int.MaxValue приводит к переполнению, но т.к. вы выполняете программу в unchecked mode, то все переполнения игнорируются и на выходе вы получаете то же -2147483648, а log'а из отрицательного числа нету, поэтому NaN.
Просто создайте исключение для int.MinValue.
А вы посмотрите, чему равно int.MinValue и чему равно int.MaxValue. В силу особенностей представления чисел, Abs(MinValue) обычно на 1 больше, чем MaxValue для любых целочисленных данных (не только для int), поэтому -int.MinValue на 1 больше чем int.MaxValue и уже не помещается в тип int. Но эту проблему наверное можно решить принудительным преобразованием -((long)number).
мне кажется проще так
sum = sum < 0 ? sum.ToString().Length - 1 : sum.ToString().Length;
public static byte GetLengthWithCascadedIfElse(int number)
{
if (number > 9 || number < (-9))
{
return (byte)(GetLengthWithCascadedIfElse(number / 10) + 1);
}
else
{
return 1;
}
}
Можно решить с помощью рекурсивной функции