Как получить размер числа в .net? - PullRequest
4 голосов
/ 29 июля 2011

Я хочу, чтобы с заданным двойным числом возвращался его «размер» (известный как | число | или номер цифры без цифр после точки), например:

12.324654 -> 2
12 -> 2
0.99 -> 0
1.01 -> 1
901 -> 3
-0.99 -> 0
-9.999 -> 1

Должна быть функция .net, с которой я не знаком, которая делает это ..

Спасибо.

Ответы [ 6 ]

9 голосов
/ 29 июля 2011

Попробуйте войти 10 (макс (абс ( число ), 0,5)) + 1 округлено в меньшую сторону.

Или, в фактическом синтаксисе C #:

(int)(Math.Log10(Math.Max(Math.Abs(number), 0.5)) + 1)

Хорошо, как это работает?

Прежде всего, p = log 10 ( x ) - основание-10 логарифм из x ;то есть значение, такое, что 10 повышается до p -й степени (или 1, за которым следует p нулей), равно x .Логарифм по существу измеряет длину числа, за исключением того, что это гладкая функция: x :

Graph of the base-10 logarithm of x

(обратите внимание, что в языках, которые непредоставить функцию логарифма base-10, мы всегда можем рассчитать ее как log 10 ( x ) = log ( x ) / log (10), где log() - логарифмическая функция в любой базе.)

Например, у нас есть

log 10 (1) = 0,0
log 10 (10) = 1,0
log 10 (100) = 2,0
log 10 (1000) = 3,0

но также, например:

log 10 (5) = 0,69897
log 10 (50) = 1.69897
log 10 (500) = 2,69897
log 10 (5000) = 3,69897

В общем n ≤ log 10 ( x ) <<em> n + 1 всякий раз, когда 10 n x <10 <sup> n + 1 .

Глядя на значения выше, это должно быть легкоy достаточно, чтобы увидеть, что, чтобы получить число цифр с основанием 10 в целом числе, мы должны округлить его логарифм с основанием 10 до ближайшего целого числа и добавить 1 (потому что мы хотим, чтобы длина 10 была 2, а не1).

Однако следует рассмотреть еще несколько крайних случаев:

Во-первых, первоначальный спрашивающий хотел, чтобы длина - x равнялась длине х .Логарифм определен только для положительных чисел, поэтому мы заменяем x на его абсолютное значение, чтобы оно всегда было положительным.

Во-вторых, первоначальный спрашивающий также хотел, чтобы длина чисел была от 0 до 1быть нулем.Однако логарифм может принимать произвольно большие отрицательные значения:

log 10 (0,1) = -1,0
log 10 (0,01) =−2.0
log 10 (0.001) = −3.0
log 10 (0.0001) = −4.0

и действительно, log 10 (0) = −∞.Чтобы удовлетворить это требование, мы просто следим за тем, чтобы число, длину которого мы вычисляем, никогда не опускалось ниже 0,5, используя его максимальное значение и 0,5 в качестве входных данных для log 10 ().(Мы можем использовать любое число от 0,1 до 1 в качестве отсечки, но 0,5 оказывается хорошей круглой двоичной дробью.)

Кроме того, мы должны обязательно добавить +1 к логарифму перед тем, как округление, так что число, которое мы округляем, всегда неотрицательно.Это потому, что (int) в C # фактически округляет отрицательные числа до до нуля.Например, поскольку log 10 (0,5) ≈ -0,3, выражение (int)Math.Log10(0.5) + 1 (округление до добавления) будет иметь значение 0 + 1 = 1, а не ожидаемое 0.

5 голосов
/ 29 июля 2011
((int)Math.Abs(12.324654)).ToString().Length

Math.Abs преобразуется в положительное число (не нужно считать отрицательный знак)
(int) опустит цифры после десятичной точки
ToString() конвертируется в строку ===> "12"
Length говорит вам, сколько символов
есть крайний случай, когда (int)( some number ) == 0, где длина даст вам 1 - вы можете этого не хотеть, поэтому помните о возможности

Теперь, что вы МОЖЕТЕ сделать, это сделать метод расширения ....

public static class Utils
{
   public static int Size(this double n)
   {
     int i = (int)Math.Abs(n);
     if ( i == 0 ) return 0;
     return  i.ToString().Length;
   }
}

12.324654.Size() == 2;
2 голосов
/ 29 июля 2011

Вы можете сделать что-то вроде ниже, чтобы учесть ваши 0 цифры, возвращающие нулевую длину

private static int CountAbsoluteDigits(double p) {
    int absolute = (int)Math.Abs(p);
    if (0 == absolute)
        return 0;
    else
        return absolute.ToString().Length;
}

...

var length = CountAbsoluteDigits(12.324654);

Это вывод, который я получил с указанными вами числами.

12.324654 -> 2
12 -> 2
0,99 -> 0
1,01 -> 1
901 -> 3
-0,99 -> 0
-9,999 -> 1

1 голос
/ 29 июля 2011

Кортси Муад Диб

int GetLength(double value){
    return ((int)Math.Abs(value*10d)).ToString().Length - 1
}
1 голос
/ 29 июля 2011

Формат кражи Квинтина:

private static int CountAbsoluteDigits(double p) {
    int ip = (int)p;
    int answer = 0;
    while (ip!=0) {
        answer++;
        ip/=10;
    }
    return answer;
}

Для этого не требуется трюк (например, abs(), if).

0 голосов
/ 29 июля 2011

Преобразование в целое число и преобразование результата в строку будет работать только в том случае, если значение находится в диапазоне от типа int. Если вам нужны значения более 2 миллиардов, вам придется либо работать с журналами, либо конвертировать double в строку.

static int GetLength(double d)
{
    d = Math.Abs(d);
    if (d < 1.0) return 0;
    if (double.IsInfinity(d)) return int.MaxValue;
    if (double.IsNaN(d)) return 0;
    return (int)Math.Floor(Math.Log10(d)) + 1;
}

static int GetLength2(double d)
{
    d = Math.Abs(d);
    if (d < 1.0) return 0;
    if (double.IsInfinity(d)) return int.MaxValue;
    if (double.IsNaN(d)) return 0;
    string s = d.ToString("E"); // returns a string in the format "1.012435E+001"
    return int.Parse(s.Substring(s.Length - 3)) + 1;
}

static void Test(double d) { Debug.WriteLine(d + " -> " + GetLength(d) + ", " + GetLength2(d)); }

static void Main(string[] args)
{
    Test(0);
    Test(0.125);
    Test(0.25);
    Test(0.5);
    Test(1);
    Test(2);
    Test(10);
    Test(10.5);
    Test(10.25);
    Test(10.1243542354235623542345234523452354);
    Test(999999);
    Test(1000000);
    Test(1000001);
    Test(999999.111);
    Test(1000000.111);
    Test(1000001.111);
    Test(double.MaxValue);
    Test(double.MinValue);
    Test(double.PositiveInfinity);
    Test(double.NegativeInfinity);
    Test(double.NaN);
    Test(double.Epsilon);
}

Результаты:

0 -> 0, 0
0.125 -> 0, 0
0.25 -> 0, 0
0.5 -> 0, 0
1 -> 1, 1
2 -> 1, 1
10 -> 2, 2
10.5 -> 2, 2
10.25 -> 2, 2
10.1243542354236 -> 2, 2
999999 -> 6, 6
1000000 -> 7, 7
1000001 -> 7, 7
999999.111 -> 6, 6
1000000.111 -> 7, 7
1000001.111 -> 7, 7
1.79769313486232E+308 -> 309, 309
-1.79769313486232E+308 -> 309, 309
Infinity -> 2147483647, 2147483647
-Infinity -> 2147483647, 2147483647
NaN -> 0, 0
4.94065645841247E-324 -> 0, 0
...