Как напечатать двойное значение, которое меньше, чем другое двойное значение?

На самом деле я работаю над выражением диапазона в С++. Так что я хочу, если у меня есть выражение типа

x<1

Затем мой

double getMax(...);

должно возвращать двойное значение, которое находится непосредственно перед 1.000 (двойная точность) в числовой строке.

Я пробовал делать это

double getMax(double& a)
{
    return (a-numeric_limits<double>::min());
}

Но я все еще получаю то же значение, что и оператор return.

Я думаю, что С++ преобразует его в ближайший double в инструкции cout.

int main()
{
    double a = 32;
    cout<<scientific<<getMax(a)<<endl;
    return 0;
}

выход:

3.200000e+001

Ответ 1

Прежде всего, вам нужно убедиться, что вы на самом деле печатаете достаточно много цифр, чтобы отобразить все отображаемые значения double. Вы можете сделать это следующим образом (убедитесь, что вы #include <iomanip> для этого):

    std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::max_digits10) << getMax(a) << std::endl;

Во-вторых, numeric_limits<>::min для этого не подходит. Если ваше начальное значение 1.0, вы можете использовать numeric_limits<double>::epsilon, что является наименьшей разницей от 1.0, которая может быть представлена.

Однако в вашем примере кода начальное значение 32. Эпсилон не обязательно работает для этого. Вычисление правого эпсилона в этом случае затруднено.

Однако, если вы можете использовать С++ 11 (*) в заголовке cmath есть функция, которая делает то, что вам нужно std::nextafter:

#include <iostream>
#include <limits>
#include <iomanip>
#include <cmath>

double getMax(double a)
{
  return std::nextafter(a,std::numeric_limits<double>::lowest());
}

int main()
{
    double a = 32;
    std::cout << std::scientific
              << std::setprecision(std::numeric_limits<double>::max_digits10)
              << getMax(a)
              << std::endl;
    return 0;
}

Я также разместил его на liveworkspace.

Объяснить:

double nextafter(double from, double to);

возвращает следующее представимое значение из в направлении to. Поэтому я указал std::numeric_limits<double>::lowest() в своем вызове, чтобы убедиться, что следующее представляемое значение меньше аргумента.

(*) См. комментарий Tony D ниже. У вас может быть доступ к nextafter() без С++ 11.

Ответ 2

Думаю, у тебя есть правильная идея. Проверьте Установка точности двойника без использования потока (ios_base:: precision) не столько для вопроса, сколько для примеров, которые они дают при использовании precision. Возможно, вы захотите попробовать что-то вроде печати с точностью 53.

То, как я обычно вижу "близко, но не совсем", связано с установкой порогового значения разности (обычно называемого epsilon). В этом случае вы не использовали бы функцию getMax, но использовали бы epsilon в вашем использовании меньше. (Вы можете сделать класс со значением epsilon и перегрузкой оператора. Я стараюсь избежать перегрузки оператора, как чума.)

В принципе, вам понадобится:

bool lessThanEpsilon(double number, double lessThan, double epsilon)
{
    return (lessThan - number >= epsilon);
}

Конечно, есть и другие разновидности. Равные значения будут проверять if Math.abs(number - equals) < epsilon