Используя LONG DOUBLE, «9223372036854775807 - 1» по-прежнему сбрасывает последнюю цифру и отображается как «9223372036854775800» - PullRequest
0 голосов
/ 16 февраля 2012

Я пытаюсь прочитать два числа и отобразить абсолютную разницу между ними. Числа становятся смехотворно большими, поэтому мне пришлось переключиться с LONG на LONG DOUBLE и просто отобразить их с точностью до 0 на десятичной дроби. Моя проблема заключается в том, что с номером, указанным в теме, когда я сканирую его в длинный двойник из строки c_str либо в процессе сканирования, последняя цифра сбрасывается, либо, скорее всего, отображение длинного двойника сбрасывает его. 9223372036854775807 - 1 должен быть 9223372036854775806, но вместо этого он отображает 9223372036854775800, и когда я перестаю проверять длинный дубль с 9223372036854775807, он просто показывает мне «9.2233720368547758e + 018" * 100

Я бы свалил все это на 2-битный процессор, но на 64-битном он все еще печатает неправильный ответ. У кого-нибудь есть способ сохранить весь номер? мои включения лишены символов, которые, похоже, мешали анализатору html.

#include iostream
#include string
#include math.h


using namespace std;

int main () {


    string line;
    std::getline(std::cin, line);


    while ( std::cin )
    {

      long double n, m, o;


      sscanf ((char *)line.c_str(),"%Lf %Lf",&n, &m);

      if(n>=m)
      {
         o = n - m;
      }
      else
      {
          o = m-n;
      }
      char buffer[100000];

    sprintf( buffer , "%0.0Lf\0", o); 

      cout << buffer << endl;
      std::getline(std::cin, line);
    }


  return 0;
}

Ответы [ 3 ]

2 голосов
/ 16 февраля 2012

Я бы прекратил использовать long double и использовал бы long long, если ваш компилятор поддерживает это.Вы сказали, что ранее использовали long, поэтому я не думаю, что вы хранили дробные части;если это правильно, то long long будет тем, что вы хотите, а не long double.Я протестировал ваш код с long long на MSVC ++ 2010, и он дал ожидаемый результат.

И, как отметил Mysticial, double совпадает с long double на многих современных компиляторах.

2 голосов
/ 16 февраля 2012

long double не требуется для обеспечения большей точности, чем double. Однако, даже если это так, вы должны сообщить компилятору, что литерал равен a long double. Без десятичной точки компилятор предположит, что 9223372036854775807 - это некое целое число. Так что вам нужно написать это как 9223372036854775807.0L.

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

0 голосов
/ 23 апреля 2015

После принятия ответа.

Числа с плавающей точкой имеют конечную точность.

В <cfloat> равно LDBL_DIG.Это число значащих десятичных цифр, которое код может считывать в long double и всегда будет выводить те же цифры снова.

Указано не менее 10 и часто 15+.9223372036854775807, с его 18 значащими десятичными цифрами, безусловно, превышает значение вашей системы LDBL_DIG.

Переключение на целочисленную математику имеет гораздо более ограниченный диапазон .long может не работать, поскольку LONG_MAX может быть таким же маленьким, как 2147483647.Лучше использовать long long, который может справиться с числами, по крайней мере, до 9223372036854775807 - достаточно большой.

...