Двойные результаты отличаются от Visual Studio 2012 и Visual Studio 2015 - PullRequest
0 голосов
/ 20 сентября 2018

Я работаю над математическим приложением в Windows 7, 64 бит.Мы недавно перешли на c ++ 11 через Visual Studio 2015 У меня есть проблема, которую я сократил до следующей маленькой программы

#include "stdafx.h"
#include "iostream"

using namespace std;


int main()
{
    const double OM = 1.10250000000000000E-36;
    std::cout.precision(20);
    std::cout <<   OM;

    int y;
    std::cin >> y;
    return 0;
}

Когда я компилирую и запускаю программу 1) ПО Visual Studio 2012 я получаюрезультат как 1.1025000000000001e-036 2) В Visual Studio 2015 с c ++ 11 я получаю результат как 1.1025000000000000611e-36

Обратите внимание на дополнительные 0 в визуальномСтудия 2012. Нам нужны одинаковые результаты.(обратите внимание, что результаты отличаются не только дополнительными 0, но и последними показанными цифрами)

Как я могу сделать то же самое (т.е. мне нужны старые результаты с дополнительным 0)?Это вызвало огромную проблему для меня, и я хочу иметь такие же результаты.

enter image description here

Причина необходимости таких же результатов.Эта программа является небольшим объяснением различий.Эта разница привела к моим ошибкам регрессии.Иногда это различие складывается, чтобы дать разные результаты.

Я надеюсь, что в Visual Studio есть некоторые переключатели компилятора и т. Д., Которые могут дать мне старые результаты.

1 Ответ

0 голосов
/ 20 сентября 2018

Старый способ Visual C ++ с трехзначным показателем представляется устаревшим расширением Visual C ++ _set_output_format .Документация гласит:

Важно

Эта функция устарела.Начиная с Visual Studio 2015, он не доступен в CRT.

Таким образом, в основном вам не повезло, но не безнадежно.

Вы можете определить свою собственную функцию печати дляудвоить и связать его с std::basic_ostream через std::ios_base::imbue.Это означает, что вам нужно определить новую локаль только для ваших нужд.

Вот эскиз решения.Вы должны заполнить детали, чтобы код хорошо работал со всеми параметрами форматирования iostream и не игнорировал такие вещи, как setprecision().Пример кода ниже - это всего лишь пример, он не делает все эти вещи.Для полного решения вам придется немного поработать (но не слишком):

template <class Char>
class my_double : public std::num_put<Char>
{
public:
    static my_double * get()
    {

        static my_double * singleton = new my_double;
        return singleton;
    }
private:
    using base = std::num_put<Char>;
    //
    // This method will format your double according to your needs.
    // Refine the code so that it reads and uses all the flags from `str`
    // and uses the `fill` character.
    //
    iter_type do_put(iter_type out, std::ios_base& str, Char fill, double v) const override
    {
        if (v < 0)
        {
            v *= -1;
            *out = '-';
            ++out;
        }
        if (v == 0.0 || std::isnan(v))
        {
            return base::do_put(out, str, fill, v);
        }
        auto exponent = static_cast<int>(std::floor(std::log10(v)));
        auto significand = v / std::pow(10.0, exponent);
        // TODO: Format according to the flags in `str`
        out = base::do_put(out, str, fill, significand);
        *(out++) = 'e';
        if (exponent < 0)
        {
            *(out++) = '-';
            exponent *= -1;
        }
        *(out++) = '0' + ( (exponent / 100) % 10);
        *(out++) = '0' + ((exponent / 10) % 10);
        *(out++) = '0' + (exponent % 10);
        return out;
    }
};

int main()
{

    // !!!
    // This is how you register your formatting function for `double`
    // !!!
    std::cout.imbue(std::locale(cout.getloc(), my_double<char>::get()));
    /// your code goes here:
}
...