1

With the below code,

int main() {
    for(;;) {
        float d;
        cin >> d;
        cout << std::to_string(d) << endl;
    }
}

to_string seems to always return a string containing a decimal point followed by six digits. Is this behavior guaranteed (excluding nan and infinity)?

According to cplusplus.com, "as many digits are written as needed to represent the integral part, followed by the decimal-point character and six decimal digits".

Emil Laine
  • 41,598
  • 9
  • 101
  • 157

2 Answers2

4

to_string seems to always return a string containing a decimal point followed by six digits. Is this behavior guaranteed (excluding nan and infinity)?

Yes. The output of std::to_string is controlled by the output std::sprintf, whose default precision is 6.

From http://en.cppreference.com/w/cpp/string/basic_string/to_string,

7,8) Converts a floating point value to a string with the same content as what std::sprintf(buf, "%f", value) would produce for sufficiently large buf.

From http://en.cppreference.com/w/cpp/io/c/fprintf, (emphasis mine)

f, F

converts floating-point number to the decimal notation in the style [-]ddd.ddd.

Precision specifies the minimum number of digits to appear after the decimal point character. The default precision is 6.


Caveat

The decimal point is not used as the decimal marker in all locales. You might get a different character for the decimal marker depending on the locale. But a decimal marker will be there regardless of locale.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    I would add the following recipe: http://stackoverflow.com/questions/16605967/set-precision-of-stdto-string-when-converting-floating-point-values?rq=1 – user3159253 Mar 25 '15 at 05:09
  • These are undoubtedly the rules in effect.... but why does the comment concerning "the alternative implementation" of `sprintf` provide a guarantee on `to_string`? – Ben Voigt Mar 25 '15 at 05:12
  • @BenVoigt, the *alternative implementation* is not relevant to the answer. I'll remove it. – R Sahu Mar 25 '15 at 05:22
  • @RSahu: But the alternative implementation was where a decimal point gets added even when there are no decimal digits. – Ben Voigt Mar 25 '15 at 05:23
  • 1
    @BenVoigt, that's true. But that applies only if the format used is `"%#f"`, which is not the case here. – R Sahu Mar 25 '15 at 05:25
  • Oh, ok, because there are 6 decimals after the floating-point, it doesn't matter that the floating-point would be omitted if there were no following digits. – Ben Voigt Mar 25 '15 at 05:28
  • 1
    @BenVoigt, the decimal point is guaranteed when `"%f"` is used, with 6 digits of precision. My understanding is that the `#` comes into play only when you use 0 digits of precision - `"%#10.0f"` will add the decimal point but `"%10.0f"` will not – R Sahu Mar 25 '15 at 05:30
  • "For a, A, e, E, f, F, g, and G conversions, the result of converting a floating-point number always contains a decimal-point character, even if no digits follow it. (Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.) For g and G conversions, trailing zeros are not removed from the result. For other conversions, the behavior is undefined." So it seems that if the value is within .0000005 of an integer, it could be printed with no decimal digits and if so, no decimal point would be output either. – Ben Voigt Mar 25 '15 at 05:33
  • Or maybe the trailing zeros *aren't* removed without `#`. – Ben Voigt Mar 25 '15 at 05:39
  • @BenVoigt, the trailing zeros are removed when g or G conversion is used without the `#`. When used with `#`, the trailing zeros are retained. – R Sahu Mar 25 '15 at 05:42
  • Decimal point is **NOT** guaranteed, see: https://github.com/nlohmann/json/issues/51 – Delgan Nov 26 '19 at 13:36
  • @Delgan, The decimal point is guaranteed but the dot character is not guaranteed. That depends on the locale. – R Sahu Nov 26 '19 at 16:41
  • @RSahu I think "decimal point" specifically refers to the dot character. Quoting Wikipedia about [decimal separator](https://en.wikipedia.org/wiki/Decimal_separator): "Any such symbol can be called a decimal mark, decimal marker or decimal sign. But symbol-specific names are also used; **decimal point** and **decimal comma** refer to an (either baseline or middle) dot and comma respectively" – Delgan Nov 26 '19 at 20:38
2

No. The decimal point can also be a comma, depending on the computer on which the program is run (controled by $LANG on Linux or other means on Windows). The C++ documentation says:

std::to_string relies on the current locale for formatting purposes

This means that when e.g. run in Germany, std::to_string uses a comma, while when run on a computer in the US, it uses a point as separator. To enforce a dot as decimal separator, you must set the locale before calls to to_string:

#include <clocale>
std::setlocale(LC_NUMERIC, "C")
cdalitz
  • 1,019
  • 1
  • 6
  • 7