Info : поиск кол-во знаков числа

 

часто при програмировании приходиться найти кол-во знаков в переменой

простым перебором со сравнением это занимает определенное время

вот приведен кусок кода в котором реализовано подобное сравнение

для нахождения кол-во знаков на которое в последствии необходимо провести нормирование

    // округляем лоты до нужной величины
   int digits;
   if (lotStep >= 1) digits = 0;             // 1
   else  if (lotStep * 10 >= 1) digits = 1;  // 0.1
         else digits = 2;                    // 0.01
   lots = NormalizeDouble(lots, digits);

Одним из решений такой задачи состоит в обратном преобразовании

выражения типа 10^х=y т.е. нам необходио найти х - величина на которую производиться

возведение в степень x*Ln(10)=Ln(y) => Exp(x*Ln(10))=Exp(Ln(y)) =>

Exp(x*Ln(10))=y

при обратной задаче мы проводим обратное преобразование

Ln(Exp(x*Ln(10)))=Ln(y) => x*Ln(10)=Ln(y) => x=Ln(y)/Ln(10)

для однозначных чисел типа 1, 10,100,1000 или 0.1,0.01,0.001 и т..д.

проблема не составляет труда, а для других которые не кратны 1 необходмо из получено выражения

выделить целую часть в результате получаем код :

int IsDigit(double y)
{
   return(MathFloor(MathLog(MathAbs(y))/MathLog(10)+1));
}


 
вау
 
супер!
 

Небольшое дополнение :

Если числа меньше 1 то получаемое значение IsDigit - отрицательные значения

 
-star- писал(а) >>
супер!

Ваш восторг от незнания матеметики?

Как Вы думаете, сколько знаков в числе 1.001? А в 0.8781? Приведенный выше способ сообщает, что 1 и 0 соответственно.

 
PapaYozh >>:

Ваш восторг от незнания матеметики?

Как Вы думаете, сколько знаков в числе 1.001? А в 0.8781? Приведенный выше способ сообщает, что 1 и 0 соответственно.

Я не проверял но просто поверил!

 

А это от меня:

// Функция возвращает количество значащих разрядов числа до указанного количества нулей.
int AmountSignificantDigits (double Value,        // Число для вычисления количества его разрядов.
                             int    AmountZeroes, // Количество нулей, которое будет считаться концом числа.
                             int    Mode)         // 0 - поиск осуществляется слева от запятой (в целой части).
                                                  // 1 - поиск осуществляется справа от запятой (в дробной части).
                                                  // 2 - поиск осуществляется во всём числе.
 {
  double AbsValue = MathAbs (Value);         // Абсолютное значение входного числа.
  double IntAbsValue = MathFloor (AbsValue); // Абсолютное значение входного числа без дробной части.
  int    i, j;
  int    Mantissa;    // Длина маетиссы.
  int    Length;      // Длина строки.
  string String = ""; // Рабочая строка для расчётов.
  // Преобразование в строку.
  switch (Mode)
   {
    case 0: // Для поиска в левой целой части числа.
     {
      if (IntAbsValue == 0) return (0);   // Если целая часть числа равна нулю, возвращаем ноль.
      // Преобразуем в строку и оставляем 15 значащих знаков.
      String = StringSubstr (DoubleToStr (IntAbsValue, 0), 0, 15);
      break;
     }
    case 1: // Для поиска в правой дробной части числа.
     {
      if (IntAbsValue == 0) Mantissa = 15;                             // Вся длина мантиссы.
      else Mantissa = 15 - StringLen (DoubleToStr (IntAbsValue, 0));   // Остающаяся длина мантиссы.
      IntAbsValue = (AbsValue - IntAbsValue) * MathPow (10, Mantissa); // Приводим к целому типу мантиссу входного числа.
      if (IntAbsValue == 0) return (0);                                // Если число равно нулю, возвращаем ноль.
      String = DoubleToStr (IntAbsValue, 0);                           // Преобразуем в строку.
      break;
     }
    case 2: // Для поиска во всём числе.
     {
      if (IntAbsValue == 0) Mantissa = 15;                             // Вся длина мантиссы.
      else Mantissa = 15 - StringLen (DoubleToStr (IntAbsValue, 0));   // Остающаяся длина мантиссы.
      // Если длина мантиссы более нуля, это число дробное. Приводим к целому типу всё входное число.
      if (Mantissa > 0)
       {
        IntAbsValue = AbsValue * MathPow (10, Mantissa);               // Приводим к целому типу всё входное число.
        if (IntAbsValue == 0) return (0);                              // Если число равно нулю, возвращаем ноль.
        String = DoubleToStr (AbsValue * MathPow (10, Mantissa), 0);   // Преобразуем в строку.
       }
      // Если длина мантиссы равно нулю, это число целое. Приводим к целому типу всё входное число. Преобразуем в строку.
      if (Mantissa == 0) String = DoubleToStr (IntAbsValue, 0);
      // Если длина мантиссы менее нуля, это число целое с длиной более 15 знаков. Преобразуем в строку.
      if (Mantissa < 0) String = StringSubstr (DoubleToStr (IntAbsValue, 0), 0, 15);
     }
   }
  Length = StringLen (String); // Длина строки.
  for (i = 0, j = 0; i < Length; i++)
   {
    if (StringSubstr (String, i, 1) == "0")
     {
      j++;
      if (j >= AmountZeroes) return (i - j + 1);
     }
    else j = 0;
   }
  return (i);
 }

// Функция для вычисления количества разрядов числа до десятичной точки.
//    Количество разрядов числа формата 1,234х10^p это показатель степени (p) при основании десять.
//    Функция возвращает количество разрядов до десятичной точки.
int Exponent (double Value,   // Число для вычислений.
              int    Limiter) // Ограничение вычислений разрядов.
 {
  int    n = 0;
  int    Exp; // Показатель степени.
  double AbsValue = MathAbs (Value);  // Берём абсолютное значение. 
  if (AbsValue * MathPow (10, Limiter) == 0) return (0); // Если число с заданной точностью равно нулю, возвращаем ноль.
  if (AbsValue < 1)                // Если число меньше единицы. 
   {
    for (Exp = 0; Exp <= Limiter; Exp++)
     {
      n = AbsValue * MathPow (10, Exp);
      if (n >= 1) return (-Exp);  // Возвращаем с обратным знаком.
     }
   }
  if (1 <= AbsValue && AbsValue < 10) return (0); // Если число между единицей и десятью, возвращаем ноль.
  if (AbsValue >= 10)             // Если число больше или равно десяти.
   {
    for (Exp = 0; Exp >= -Limiter; Exp--)
     {
      n = AbsValue * MathPow (10, Exp);
      if (n <= 9) return (-Exp); // Возвращаем с обратным знаком.
     }
   }
 }
 

коротко и элегантно :)

 
int LeftDigits(double aValue){
   return(StringFind(DoubleToStr(aValue,1),".",0));
}
 
Zhunko писал(а) >>

Тогда так:

Это для незатейливых вычислений...

Надо еще нули справа после запятой откинуть.

Причина обращения: