Извлечение отдельных цифр из числа с плавающей точкой

StackOverflow https://stackoverflow.com/questions/339150

Вопрос

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


Спасибо за совет!Я надеялся на решение, которое не будет преобразовываться из float -> string -> int, но я подумай это лучший способ уйти от проблем квантования с плавающей запятой.В итоге я выбрал boost::format и просто ссылался на отдельные символы строки.Я не вижу в этом огромной разницы в производительности по сравнению с использованием комбинаций modf и fmod для попытки получить цифру из числа с плавающей точкой (вероятно, это происходит именно за кулисами, только более надежно, чем моя реализация).

Это было полезно?

Решение

Внутреннее представление чисел с плавающей точкой не такое, как вы видите. Вы можете бросить только на перемешивание.

Чтобы разыграть, сделайте это:

char string[99];
sprintf(string,"%f",floatValue);

Или посмотрите это: http: // www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.1

Статья в Википедии может объяснить больше о представлении: http://en.wikipedia.org/wiki/ Floating_point

Другие советы

О, есть много способов преобразовать в строку. (Хотя я действительно предпочитаю snprintf() я сам.)

Или вы могли бы преобразовать в int и извлечь цифры с помощью модуля и целочисленного деления.Вы можете подсчитать количество цифр с помощью log{base10}.

(Помните:log{baseA}_X / log{baseA}_B = log{BaseB}_X.)

Пример:

#define SHOW(X) cout << # X " = " << (X) << endl

int
main()
{
  double d = 1234.567;

  SHOW( (int(d)%10000) / 1000 );
  SHOW( (int(d)%1000)  / 100  );
  SHOW( (int(d)%100)   / 10   );
  SHOW( (int(d)%10)           );
  SHOW( (int(d*10)  % 10)     );
  SHOW( (int(d*100) % 10)     );
  SHOW( (int(d*1000)% 10)     );

  SHOW( log(d)/log(10) );
}

Хотя вам следовало бы использовать static_cast ...

Следите за экспоненциальными обозначениями.При очень больших или очень маленьких числах у вас может возникнуть проблема.

Числа с плавающей запятой также имеют проблемы с округлением, которые могут вас огорчить.(Это та же причина, по которой мы не используем operator== между двумя дублями.Или почему вы не можете полагаться на a * b == b * a.В зависимости от точных значений a и b, они могут очень незначительно отличаться примерно на 10^-25.)

Вы можете выполнять преобразование между string и float только с помощью boost::lexical_cast .Однако вы не можете напрямую проиндексировать форму с плавающей запятой - она внутренне не хранится в виде десятичных цифр.Вероятно, это не такая уж большая проблема.Для вашего пользовательского интерфейса вы, скорее всего, в любом случае сохраните строковую форму числа с преобразованиями в float и из float в getter / setter.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top