C Проверка или преобразование показателей степени

У меня есть показатели в представленном формате: "1.45e004" или "1.45e-04" или "-1.45e004".

[обратите внимание на знак минус в третьем]

Проверка (==, !=, >, ‹, ‹=, >= и т. д.) не работает с показателями степени [неверные результаты или результаты не возвращаются] в их текущем формате.

Однако преобразование экспоненты с помощью fabs работает для первых двух, но не для последнего, поскольку fabs удаляет знак минус (следовательно, значение становится положительным, а не отрицательным, как должно быть).

Мои вопросы таковы:

1) Есть ли способ преобразовать экспоненты в абсолютные значения, которые включали бы значения со знаком?

[фабрики не могут этого сделать]

OR

2) Есть ли способ [или функция(и)] для сравнения одного показателя степени с другим (должна быть возможность делать ==, !=, >, ‹, >=, ‹=)?

OR

3) Есть ли способ извлечь два значения из экспоненты.

Например: "-1.45e-04" [Value1 = -1.45, Value2 = -4].

Ответы на вопросы 1 и/или 2 предпочтительнее, так как 3 — это обходной путь, который может иметь проблемы с реализацией (однако он есть в случае 1 и 2, не нет подходящих ответов).

[Примечание: можно использовать методы С++, хотя предпочтительнее избегать потока]

Спасибо

int main(void)
{
    //Not the actual program, but simple enough
    char Arr[100];
    double T1, T2;

    sprintf(Arr,"-1.45e004");
    T1 = atof(Arr);

    printf("%f\n",fabs(T1)); //Fails to show the minus sign

    return 0;
}

Общая цель может быть достигнута при ответе на любой из трех вопросов:

Либо: 1) Прямое сравнение (с использованием функции) между двумя показателями в заданном формате, чтобы увидеть, являются ли они одинаковыми, не одинаковыми, больше, меньше (и т. д.) для сортировки от наибольшего показателя к наименьшему показателю (не содержится в программе, так как то, как реализована сортировка, не имеет значения: нужно решить только проверку).

2) Косвенное сравнение, путем преобразования его в другой тип, который можно сравнивать напрямую.

3) Прямое сравнение с использованием неудобного обходного пути путем отдельного сравнения двух чисел в показателе степени.

[Подробности фона]

Фактическая программа охватывает 7 файлов заголовков и 1 файл cpp, поэтому я не могу отобразить конкретный сегмент, поскольку он переплетается.

Задача такова: файлы, загруженные со спутника ACE, разбираются как аргументы, загружаются в память, преобразуются в соответствующие им типы. Затем сохраненные типы сортируются и подготавливаются (текущий этап) для отображения графа (еще не реализовано).

На данный момент я имею дело с экспонентами (хранящимися в текстовых файлах спутника ACE в формате, указанном выше). Эти показатели необходимо просмотреть, чтобы найти наибольший показатель и наименьший показатель, чтобы можно было правильно расположить график между ними. После этого каждый показатель степени будет сравниваться, чтобы увидеть, больше ли он (выше на графике) или меньше (ниже на графике) заданного набора чисел.

Для этой задачи мне нужны сравнения между показателями. Учитывая, что я неопытен с ними, я решил спросить здесь.


person SightS2    schedule 13.04.2011    source источник
comment
Экспоненты? Абсолюты? Проверка экспоненты? Преобразование экспоненты?   -  person NPE    schedule 13.04.2011
comment
Когда вы используете fabs для экспоненты, хранящейся в двойном, она возвращает абсолют [не цитируйте меня, я сам не уверен в экспонентах]. Таким образом, вместо 1.45e004 будет отображаться 14500.0.   -  person SightS2    schedule 13.04.2011
comment
По общему признанию, я не совсем уверен, о чем вы спрашиваете, так что простите меня, если я был наивен.   -  person SightS2    schedule 13.04.2011
comment
Да, это то, что делает fabs. В любом случае, если вы хотите получить помощь, я предлагаю вам опубликовать код и четко объяснить, что именно в этом коде работает не так, как вы ожидаете.   -  person NPE    schedule 13.04.2011
comment
Число с плавающей запятой представляется в соответствии со стандартом, а не в соответствии с этим или другим шаблоном форматирования строк. Пожалуйста, предоставьте какой-нибудь код, иначе вам трудно помочь.   -  person Itamar Katz    schedule 13.04.2011
comment
Я чувствую, что вы педантичны. Я никогда не говорил, что именно так должны соответствовать числа с плавающей запятой. Я сказал, что именно так были представлены экспоненты (в программе), которые до сих пор считаются приемлемыми, если фабрики могут правильно преобразовать их. Показатели хранятся в текстовом файле, но я не уверен, зачем мне нужно подробно объяснять это, учитывая, что это бесполезно, и я достаточно изложил параметры проблемы.   -  person SightS2    schedule 13.04.2011
comment
Было бы полезно, если бы вы описали здесь свою общую цель, а не задавали вопросы о реализации, которая может подходить или не подходить для вашей цели. Похоже, вы делаете здесь что-то необычное, так что вам придется нам помочь.   -  person Greg Hewgill    schedule 13.04.2011
comment
Я добавил несколько голов. Я думаю, что добавлю некоторые детали фона.   -  person SightS2    schedule 13.04.2011
comment
@SightS2: меня очень смущает использование вами слова экспонента. Насколько мне известно, -1.45e-04 — это число с плавающей запятой, представленное значащим (или мантиссом), в примере -1.45 и показатель степени, в примере -04. Итак, когда вы говорите, что хотите преобразовать/сравнить показатели степени, вы действительно имеете в виду показатели степени или вы на самом деле имеете в виду целые числа?   -  person Björn Pollex    schedule 13.04.2011
comment
@ SightS2: вы создали путаницу, ссылаясь на fabs (абсолютное значение - это, по сути, одно и то же число без знака). Это не имеет ничего общего с преобразованием чисел в/из поплавков. В коде, который вы опубликовали, atof - это то, что преобразует строковое значение в число с плавающей запятой (что не сработало для меня в ideone), как только вы получите его в числах с плавающей запятой, вы можете просто выполнить сравнения, о которых вы говорите.   -  person forsvarir    schedule 13.04.2011
comment
Прочитайте эту статью en.wikipedia.org/wiki/Floating-point_number и некоторые статьи. связанные с ним, такие как Exponent. Вы неправильно используете терминологию, а также, похоже, путаете строковое представление чисел с самими числами. Ваш вопрос как есть не имеет смысла.   -  person atzz    schedule 13.04.2011


Ответы (4)


Непонятно, почему вы звоните fabs() в этой строке:

printf("%f\n",fabs(T1)); //Fails to show the minus sign

Вот что делает fabs(), он делает отрицательные числа положительными. Возможно, вы хотите этого:

printf("%f\n",T1);

Сравнение двух чисел с плавающей запятой можно выполнить напрямую:

double x = 12.345e67;
double y = 6.543e-2;
if (x > y) {
    puts("x is greater than y");
}
person Greg Hewgill    schedule 13.04.2011
comment
Значит, нет проблем между сравнением двух показателей? Если это так, то я манекен. - person SightS2; 13.04.2011
comment
Правильно, сравнения чисел с плавающей запятой встроены в C++. - person Greg Hewgill; 13.04.2011
comment
@Greg: Хотя, как упоминает @unwind в своем ответе, при сравнении чисел с плавающей запятой есть подводные камни. - person Björn Pollex; 13.04.2011
comment
Я знал, что это так для чисел с плавающей запятой (отсюда и моя попытка преобразования с помощью fabs), но я не думал, что это делается с показателями степени. Я официально манекен. Я выберу этот ответ, а потом останусь пристыженным. - person SightS2; 13.04.2011
comment
@Space_Cowboy, что это за подводные камни? Мне нужно быть осторожным. - person SightS2; 13.04.2011
comment
@SightS2: прочитайте статью @unwind по ссылкам в его ответе. Действительно, оправданий нет. Вы должны прочитать это. - person Björn Pollex; 13.04.2011
comment
@SightS2: я думаю, что эта статья может быть немного выше вашего понимания, но обязательно прочитайте ее как-нибудь. Основная ошибка заключается в том, что числа с плавающей запятой неточны. Каждый раз, когда вы вычисляете с ними, вы, вероятно, немного теряете точность. В большинстве случаев это неважно, но, как правило, НЕ сравнивайте числа с плавающей запятой на равенство. Два математически эквивалентных вычисления могут быть выполнены на компьютере с небольшими различиями в результатах. Вместо a == b используйте fabs(a - b) < 1e-9 (для удвоений; измените константу для чисел с плавающей запятой) или что-то в этом роде. - person David Thornley; 14.04.2011

Кажется, вам нужно прочитать О чем должен знать каждый программист Арифметика с плавающей запятой, чтобы, по крайней мере, помочь вам со словарем.

Возможно, вы можете вычислить показатель степени, используя:

const double exp = log(value) / log(10.0);

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

ОБНОВЛЕНИЕ: чтобы сравнить числа, просто сделайте это. Все ваши три примера значений являются просто допустимыми числами с плавающей запятой, и их можно напрямую сравнивать с помощью стандартных встроенных операторов.

person unwind    schedule 13.04.2011
comment
Я пытаюсь определить, больше ли одно число с плавающей запятой, чем другое. Это будет использоваться для определения максимума/минимума (для графика), а затем позиции, которую число займет на графике. - person SightS2; 13.04.2011
comment
Я не могу использовать журнал или другие функции, так как числа не генерируются в программе (показатели сохраняются в формате, указанном в вопросе: они в текстовом файле, данные со спутника ACE). - person SightS2; 13.04.2011
comment
Ваша информация также была полезной, но я не думаю, что могу принять два ответа. - person SightS2; 13.04.2011

Я думаю, что вы хотите сделать, это извлечь части коэффициента и основы из числа, выраженного в экспоненциальном представлении. Для этого нет стандартной библиотечной функции, но вы можете легко написать ее:

static int
extract_coeff_and_base (double d, char *coeff, char *base)
{
  char buffer[50];
  size_t i;
  size_t len;

  sprintf (buffer, "%E\n", d);
  len = strlen (buffer);
  i = strcspn (buffer, "E");
  if (i < len)
    {
      memcpy (coeff, buffer, i);
      coeff[i] = 0;
      memcpy (base, buffer + i + 1, len - i);
      base[len - i] = 0;
      return 0;
    }
  return 1;
}

Использование:

int
main (int argc, char **argv)
{
  double d = atof (argv[1]);
  char coeff[20];
  char base[20];

  if (extract_coeff_and_base (d, coeff, base) == 0)
    {
      printf ("coefficient=%s, base=%s\n", coeff, base);
    }
  return 0;
}

Тесты:

$ ./test.exe 1.45e004
coefficient=1.450000, base=+04

$ ./test.exe 1.45e-04
coefficient=1.450000, base=-04

$ ./test.exe -1.45e004
coefficient=-1.450000, base=+04
person Vijay Mathew    schedule 13.04.2011

Вы должны найти то, что ищете в этом примере:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

const char *nums[] = {"1.45e004", "1.45e-04", "-1.45e004", NULL};

int main() {
  const char **numstring = nums;
  while (*numstring != NULL) {
    double num = strtod(*numstring, NULL);
    double sign = copysign(1.0, num);
    double exponent = trunc(log10(sign * num));
    double mantissa = num / pow(10, exponent);
    printf("%s -> %g, mantissa=%f, exponent=%f\n", *numstring, num, mantissa, exponent);
    numstring++;
  }
  return 0;
}
person odrm    schedule 13.04.2011