Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CString.Format produces different values with the same precision

Sorry for probably stupid question, as I am C# developer it is really difficult for me to find some ideas.

We are in progress of migration from VC++ 2013 to VC++ 2019. We have 2 similar VMs with VC++2013 and VC++2019 installed. Projects are using VC++2019 already. When running on 2 VMs results for simple evaluation are different:

CString Value;
int precision = 8;
double number = 50.634765625;
String^ RetValue;

Value.Format(_T("%.*f"), precision, number);
RetValue = gcnew String(Value.GetString());

On one VM (Win 7 64bit) we have RetValue "50.63476563" on another VM (win10 64bit) we have - "50.63476562" all tools I expect are the same (difficult to say 100% as there a lot installed, but most important c++ are).

When converting and running projects under VS2013 results on both VM are the same - "50.63476563".

Are there any option settings that control formatting? Or why in case of one VM truncation was selected in favor of rounding?

UPDATE So the problem is really related to VS2013/VS2019 difference. I found why we have different results on 2 VMs using the same VS2019. So:

  1. VS2013 rounding of 50.634765625 == VS 2019 rounding for Release
  2. VS2013 rounding of 50.634765625 != VS 2019 rounding for Debug

in both cases rounding direction is to nearest. So MSFT interprets to nearest differently in Release/Debug. C++ compiler option that makes difference /MD vs /MDd.

Could not find any other way except of switching to /MD to force rounding go old way for whole project in debug.

like image 936
Yauhen.F Avatar asked Sep 04 '20 15:09

Yauhen.F


People also ask

How do I set precision in printf?

A printf precision specification always begins with a period (.) to separate it from any preceding width specifier. Then, like width, precision is specified in one of two ways: Directly, through a decimal digit string. Indirectly, through an asterisk (*).

How do I convert a double to a string in MFC?

A double can be converted into a string in C++ using std::to_string. The parameter required is a double value and a string object is returned that contains the double value as a sequence of characters.


1 Answers

We found a difference between 2013 and 2017 in our testing. We were seeing differences in rendering the number .249500 to three digits. 2013 = 0.250 whereas 2017 = 0.249. Consider this example:

#include <stdio.h>

// little endian bytes, to avoid parsing differences between both compilers
unsigned char bytesOfDouble[] = {0x56, 0x0E, 0x2D, 0xB2, 0x9D, 0xEF, 0xCF, 0x3F}; 
double& dVal = reinterpret_cast<double&>(bytesOfDouble);

void PrintDouble(const double& d)
{
    printf("printf (%%.3f): %.3f\n", d);
    printf("printf (%%.3g): %.3g\n", d);

    printf("printf (%%f)  : %f\n", d);
    printf("printf (%%g)  : %g\n", d);
}

int main(int argc, char** argv)
{
    PrintDouble(dVal);
    return 0;
}

If you compile it with VS2013 and VS2017, you get different results. If you try g++ or clang, you get the same results as VS2017.

How to get the same results between the two? IDK... I think MS definitely changed their underlying C runtime.

like image 94
Joseph Willcoxson Avatar answered Oct 02 '22 09:10

Joseph Willcoxson