Учитывая двойное число, нужно найти, сколько всего цифр

У меня есть двойник, который не обязательно положительный, но обычно. Это может быть 0.xxxx000, или X.xxxx00000, или XX.00000, или 0.xxx0xxx00000, где в конце концов справа от последнего числа будут все 0. Мне нужно следить за количеством цифр. У меня были проблемы с этим, любая помощь? Это С.


person cdietschrun    schedule 28.03.2011    source источник
comment
что ты пробовал? можете ли вы сделать что-то, где вы подсчитываете количество нулей с каждого конца двойного числа в строковой форме, а затем выясняете разницу между двумя итераторами, чтобы получить свой счет?   -  person Anon    schedule 28.03.2011
comment
Я пробовал циклы, в которых я пытаюсь разделить каждую цифру до тех пор, пока не останется только 0,0000000000 .., но он никогда не сравнивался с 0,000000 ... правильно и никогда не останавливался. Затем я попытался с другого направления, где я вычитал и умножал число, пока вычитание не достигло 0, но во многих крайних случаях это нарушается.   -  person cdietschrun    schedule 28.03.2011
comment
Сколько цифр в результате 1,0/3? То же самое для любого двойного вычисления. Вы выбираете количество цифр.   -  person Hans Passant    schedule 28.03.2011


Ответы (3)


Используйте sprintf, чтобы превратить его в строку и выполнить любой подсчет/тестирование, которое вам нужно сделать с цифрами.

person jonsca    schedule 28.03.2011
comment
sprintf преобразует не более некоторого количества цифр по умолчанию, которое может быть переопределено параметром точности спецификатора формата. Например. sprintf(s,"%.7f",x); - преобразует до 7 цифр после '.'. Поэтому использование sprintf определенно не является решением. - person Serge Dundich; 28.03.2011
comment
Хороший вопрос, я думал, что были некоторые возможные проблемы с точностью. - person jonsca; 28.03.2011
comment
@Serge Dundich: тогда почему бы и не sprintf( s, "%.50f", x);? Конечно, вопрос не совсем ясен (особенно с учетом проблемы с основанием 2 и основанием 10, которую вы так хорошо описываете), но ответ Йонски может быть тем, что ищет спрашивающий. - person tomlogic; 28.03.2011
comment
@tomlogic: sprintf( s, "%.52f", x ) может быть в порядке, если реализация sprintf идеальна (это, скорее всего, неверно). В любом случае, 52 — это какое-то странное магическое число, верное только для определенного двойного формата, который не является обязательным по стандарту C. - person Serge Dundich; 29.03.2011

Двойной имеет 52 бита мантиссы плюс неявный бит «1», поэтому вы должны иметь возможность ввести двойной указатель на 64-битное целое число (получив необработанные биты в целое число), &= это с (1‹‹ 52)-1 и |= результат с (1‹‹52).

Log10 этого будет числом десятичных цифр.

Тем не менее, я почти склонен сказать: «Используйте решение Джонски», потому что оно настолько гениально простое (в любом случае оно заслуживает +1 за то, что это KISS).

person Damon    schedule 28.03.2011
comment
Хорошо спасибо большое. Однако смещение битов может быть приятным и быстрым. - person jonsca; 28.03.2011
comment
Log10 этого будет числом десятичных цифр. Нет! Это не так. Рассмотрим пример: 1+1/2^52. Сколько десятичных цифр? Правильный ответ — 52. Но log10(2^52+1) гораздо меньше. - person Serge Dundich; 28.03.2011
comment
Логарифм по основанию N любого числа — это количество цифр, считая по основанию N. Или, точнее, следует говорить ceil(log-N), потому что, очевидно, дробных цифр нет (если вы вычислите 4,1 цифры, это будет 5). Ваш пример 1 + 1/2 ^ 52 неприменим, поскольку это число вообще не может быть правильно представлено с двойной точностью. Кроме того, хорошо известно, что IEEE 754 double имеет 16 значащих десятичных знаков (или меньше), ваша цифра 52 никоим образом не может быть правильной. - person Damon; 28.03.2011
comment
Логарифм по основанию N любого числа — это количество цифр, считая по основанию N. Истинный. Но что заставляет вас думать, что количество десятичных цифр в числе, рассчитанном с помощью вашего метода, равно количеству десятичных цифр после точки перед всеми нулями в десятичном представлении этого двойного значения? На самом деле эти значения почти полностью не связаны. - person Serge Dundich; 29.03.2011
comment
Ваш пример 1 + 1/2 ^ 52 неприменим, поскольку это число вообще не может быть правильно представлено с двойной точностью. Не правда. У вас есть 52 бита с плавающей запятой мантиссы плюс неявная 1 перед ними. 64-битное шестнадцатеричное представление двойного числа 1+1/2^52 с типизированным обозначением имеет вид 3ff0000000000001 (смотрите здесь). 1+1/2^52 — самый мягкий пример. Для любого двойного числа ваш метод всегда производит число в диапазоне от 2 ^ 52 до 2 ^ 53-1, а количество десятичных цифр в любом из этих чисел равно 16. - person Serge Dundich; 01.04.2011
comment
Мы можем принять 1,5 = 1 + 1/2. Ваш метод выдает число 0x18000000000000, а его log10 равно 16 (как всегда), что никак не связано с 1,5 (это просто максимальная десятичная точность double). - person Serge Dundich; 01.04.2011
comment
Эх... ладно, попробую в последний раз: 1/2^52 = 0,000000000000000022204460492503131. (двойной)(0,00000000000000022204460492503131) = 0,000000000000000022204, и (двойной)(1,0 + 0,000000000000000022204460492503131) = 1,000000000000000 IEEE 754 double может представлять 15,955 (+ 1) десятичных цифр, не более. Неважно, сколько цифр может или не может быть, даже теоретически, после этого. Их просто нет, у двойника их нет. Все, что находится между 1.0000000000000002 и 1.00000000000000003, является одним и тем же числом. - person Damon; 01.04.2011

Представление числа double не десятичное, а двоичное (как и все остальные числа в компьютере). Проблема, которую вы определили, на самом деле не имеет большого смысла. Рассмотрим пример: число 1.2 преобразуется в двоичное - 1+1/5 = 1.(0011) двоичное [0011 в периоде]. Если вы сократите его до 52-битной точности (двойной), у вас будет 1,0011001100110011001100110011001100110011001100110011, что равно 1+(1-1/2^52)/5. Если вы точно представите это число в десятичной форме, вы получите 52 десятичных знака перед всеми нулями, что намного больше, чем максимальная десятичная точность двойного числа, которая составляет 16 цифр (и все эти цифры представления от 17 до 52 просто бессмысленны) .

В любом случае, если у вас есть чисто абстрактная проблема (например, в школе):

int f( double x )
{
  int n = 0;

  x = fabs(x);
  x -= floor(x);

  while( x != floor(x) )
  {
    x *= 2;
    ++n;
  }

  return n;
}

Функция возвращает количество двоичных цифр перед всеми нулями, а также количество десятичных цифр перед всеми нулями (последняя десятичная цифра всегда 5, если возвращаемое значение > 0).

person Serge Dundich    schedule 28.03.2011