According to my ISO C book, we need
"%#.16g"
since the # will cause the decimal point to be retained always.
Unfortunately, this will print
42.00000000000000
(14 zeroes)
That is better than an integer, but it will increase the size of the output JSON file. Ideally the code could be altered to scan the buffer before returning. If it is a decimal followed by all zeroes, it should be truncated to just the decimal.
42.
That's easy code to write, but I am having trouble with Subversion right now. I've made this change in my local copy.
std::string valueToString( double value )
{
char buffer[32];
#ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
#else
sprintf(buffer, "%#.16g", value);
#endif
char* last = buffer + 30;
while(last > buffer && *last == '0') --last;
if (*last == '.') *(last+1) = '\0';
return buffer;
}
The tests still pass. (By the way, StyledStreamWriter uses tabs instead of spaces so that the output file-size is dominated by actual data.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is better (and fixes a bug). It truncates zeroes even if not all digits after the decimal are zero, and it keeps the last zero for clarity.
std::string valueToString( double value )
{
std::cerr << "double:" << value << "\n";
char buffer[32];
#ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
#else
sprintf(buffer, "%#.16g", value);
#endif
char* ch = buffer + strlen(buffer) - 1;
if (*ch != '0') return buffer; // nothing to truncate, so save time
while(ch > buffer && *ch == '0'){
--ch;
}
char* last_nonzero = ch;
while(ch >= buffer){
switch(*ch){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
--ch;
continue;
case '.':
// Truncate zeroes to save bytes in output, but keep one.
*(last_nonzero+2) = '\0';
std::cerr << "current:" << buffer << std::endl;
return buffer;
default:
return buffer;
}
}
return buffer;
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When a value is 42.0, it is printed as '42', sans the decimal point. Then it is read back as an integer!
The problem is here:
std::string valueToString( double value )
{
char buffer[32];
sprintf(buffer, "%.16g", value);
return buffer;
}
According to my ISO C book, we need
"%#.16g"
since the # will cause the decimal point to be retained always.
Unfortunately, this will print
42.00000000000000
(14 zeroes)
That is better than an integer, but it will increase the size of the output JSON file. Ideally the code could be altered to scan the buffer before returning. If it is a decimal followed by all zeroes, it should be truncated to just the decimal.
42.
That's easy code to write, but I am having trouble with Subversion right now. I've made this change in my local copy.
std::string valueToString( double value )
{
char buffer[32];
#ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
#else
sprintf(buffer, "%#.16g", value);
#endif
char* last = buffer + 30;
while(last > buffer && *last == '0') --last;
if (*last == '.') *(last+1) = '\0';
return buffer;
}
The tests still pass. (By the way, StyledStreamWriter uses tabs instead of spaces so that the output file-size is dominated by actual data.)
This is better (and fixes a bug). It truncates zeroes even if not all digits after the decimal are zero, and it keeps the last zero for clarity.
std::string valueToString( double value )
{
std::cerr << "double:" << value << "\n";
char buffer[32];
#ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
#else
sprintf(buffer, "%#.16g", value);
#endif
char* ch = buffer + strlen(buffer) - 1;
if (*ch != '0') return buffer; // nothing to truncate, so save time
while(ch > buffer && *ch == '0'){
--ch;
}
char* last_nonzero = ch;
while(ch >= buffer){
switch(*ch){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
--ch;
continue;
case '.':
// Truncate zeroes to save bytes in output, but keep one.
*(last_nonzero+2) = '\0';
std::cerr << "current:" << buffer << std::endl;
return buffer;
default:
return buffer;
}
}
return buffer;
}