Извлечение отдельных цифр из поплавка - PullRequest
2 голосов
/ 04 декабря 2008

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


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

Ответы [ 3 ]

5 голосов
/ 04 декабря 2008

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

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

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

3 голосов
/ 04 декабря 2008

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

Или вы можете преобразовать в int и вытянуть цифры с модулем и целочисленным делением. Вы можете посчитать количество цифр с помощью журнала {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 == между двумя числами типа double. Или почему вы не можете полагаться на a * b == b * a. В зависимости от точных значений a & b они могут незначительно отличаться около 10 ^ -25.)

0 голосов
/ 04 декабря 2008

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

...