зеркало из https://github.com/microsoft/STL.git
Fix ostream << floating_point not correctly handling precision (#1173)
1. Hexfloat output now ignores precision as required by the standard. (Fixes #1125.) 2. Zero precision is now correctly passed to sprintf. 3. Negative precision no longer crashes.
This commit is contained in:
Родитель
465d0a5e13
Коммит
0b81475cc8
|
@ -1146,6 +1146,45 @@ __PURE_APPDOMAIN_GLOBAL locale::id num_get<_Elem, _InIt>::id;
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif // __clang__
|
#endif // __clang__
|
||||||
|
|
||||||
|
// STRUCT TEMPLATE _Hex_float_precision
|
||||||
|
template <class _Ty>
|
||||||
|
struct _Hex_float_precision;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct _Hex_float_precision<double> {
|
||||||
|
// the number of hexits needed to represent (DBL_MANT_DIG - 1) bits after the radix point exactly
|
||||||
|
static constexpr int value = ((DBL_MANT_DIG - 1) + 3) / 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct _Hex_float_precision<long double> {
|
||||||
|
// the number of hexits needed to represent (LDBL_MANT_DIG - 1) bits after the radix point exactly
|
||||||
|
static constexpr int value = ((LDBL_MANT_DIG - 1) + 3) / 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FUNCTION TEMPLATE _Float_put_desired_precision
|
||||||
|
template <class _Ty>
|
||||||
|
int _Float_put_desired_precision(const streamsize _Precision, const ios_base::fmtflags _Float_flags) {
|
||||||
|
const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific);
|
||||||
|
if (_Is_hex) {
|
||||||
|
return _Hex_float_precision<_Ty>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_Precision > 0) {
|
||||||
|
return static_cast<int>(_Precision);
|
||||||
|
} else if (_Precision == 0) {
|
||||||
|
const bool _Is_default_float = _Float_flags == 0;
|
||||||
|
if (_Is_default_float) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
constexpr int _Default_precision = 6;
|
||||||
|
return _Default_precision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CLASS TEMPLATE num_put
|
// CLASS TEMPLATE num_put
|
||||||
template <class _Elem, class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem>>>
|
template <class _Elem, class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem>>>
|
||||||
class num_put : public locale::facet { // facet for converting encoded numbers to text
|
class num_put : public locale::facet { // facet for converting encoded numbers to text
|
||||||
|
@ -1292,10 +1331,14 @@ protected:
|
||||||
_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, double _Val) const { // put formatted double to _Dest
|
_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, double _Val) const { // put formatted double to _Dest
|
||||||
string _Buf;
|
string _Buf;
|
||||||
char _Fmt[8];
|
char _Fmt[8];
|
||||||
bool _Isfixed = (_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed;
|
const auto _Float_flags = _Iosbase.flags() & ios_base::floatfield;
|
||||||
streamsize _Precision = _Iosbase.precision() <= 0 && !_Isfixed ? 6 : _Iosbase.precision(); // desired precision
|
const bool _Is_fixed = _Float_flags == ios_base::fixed;
|
||||||
size_t _Bufsize = static_cast<size_t>(_Precision);
|
const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific);
|
||||||
if (_Isfixed && 1e10 < _CSTD fabs(_Val)) { // f or F format
|
const streamsize _Precision = _Is_hex ? -1 : _Iosbase.precision(); // precision setting
|
||||||
|
const int _Desired_precision =
|
||||||
|
_Float_put_desired_precision<double>(_Precision, _Float_flags); // desired precision
|
||||||
|
size_t _Bufsize = static_cast<size_t>(_Desired_precision);
|
||||||
|
if (_Is_fixed && 1e10 < _CSTD fabs(_Val)) { // f or F format
|
||||||
int _Ptwo;
|
int _Ptwo;
|
||||||
(void) _CSTD frexp(_Val, &_Ptwo);
|
(void) _CSTD frexp(_Val, &_Ptwo);
|
||||||
_Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L;
|
_Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L;
|
||||||
|
@ -1312,10 +1355,14 @@ protected:
|
||||||
_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long double _Val) const { // put formatted long double to _Dest
|
_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long double _Val) const { // put formatted long double to _Dest
|
||||||
string _Buf;
|
string _Buf;
|
||||||
char _Fmt[8];
|
char _Fmt[8];
|
||||||
bool _Isfixed = (_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed;
|
const auto _Float_flags = _Iosbase.flags() & ios_base::floatfield;
|
||||||
streamsize _Precision = _Iosbase.precision() <= 0 && !_Isfixed ? 6 : _Iosbase.precision(); // desired precision
|
const bool _Is_fixed = _Float_flags == ios_base::fixed;
|
||||||
size_t _Bufsize = static_cast<size_t>(_Precision);
|
const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific);
|
||||||
if (_Isfixed && 1e10 < _CSTD fabsl(_Val)) { // f or F format
|
const streamsize _Precision = _Is_hex ? -1 : _Iosbase.precision(); // precision setting
|
||||||
|
const int _Desired_precision =
|
||||||
|
_Float_put_desired_precision<long double>(_Precision, _Float_flags); // desired precision
|
||||||
|
size_t _Bufsize = static_cast<size_t>(_Desired_precision);
|
||||||
|
if (_Is_fixed && 1e10 < _CSTD fabsl(_Val)) { // f or F format
|
||||||
int _Ptwo;
|
int _Ptwo;
|
||||||
(void) _CSTD frexpl(_Val, &_Ptwo);
|
(void) _CSTD frexpl(_Val, &_Ptwo);
|
||||||
_Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L;
|
_Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L;
|
||||||
|
|
|
@ -213,9 +213,109 @@ void test_main() { // test basic workings of ostream definitions
|
||||||
outs << STD hexfloat << 2.0;
|
outs << STD hexfloat << 2.0;
|
||||||
STD string ans = outs.str();
|
STD string ans = outs.str();
|
||||||
const char* buf = ans.c_str();
|
const char* buf = ans.c_str();
|
||||||
CHECK_STR(buf, "0x1.000p+1");
|
CHECK_STR(buf, "0x1.0000000000000p+1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outs.precision(0);
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD defaultfloat << 1.5;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD scientific << 2.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2e+00");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD hexfloat << 2.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-1);
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD defaultfloat << 1.5;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.5");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.000000");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD scientific << 2.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2.000000e+00");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD hexfloat << 2.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-49);
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.000000");
|
||||||
|
|
||||||
|
outs.precision(3);
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD defaultfloat << 1.5L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.5");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.000");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD scientific << 2.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2.000e+00");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD hexfloat << 2.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(0);
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD defaultfloat << 1.5L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD scientific << 2.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2e+00");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD hexfloat << 2.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-1);
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD defaultfloat << 1.5L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.5");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.000000");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD scientific << 2.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "2.000000e+00");
|
||||||
|
|
||||||
|
outs.str("");
|
||||||
|
outs << STD hexfloat << 2.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-49);
|
||||||
|
outs.str("");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_STR(outs.str().c_str(), "1.000000");
|
||||||
|
|
||||||
// test Boolx inserter
|
// test Boolx inserter
|
||||||
const Boolx no(0), yes(1);
|
const Boolx no(0), yes(1);
|
||||||
outs.str("");
|
outs.str("");
|
||||||
|
|
|
@ -208,7 +208,107 @@ void test_main() { // test basic workings of ostream definitions
|
||||||
outs << STD hexfloat << 2.0;
|
outs << STD hexfloat << 2.0;
|
||||||
STD wstring ans = outs.str();
|
STD wstring ans = outs.str();
|
||||||
const wchar_t* buf = ans.c_str();
|
const wchar_t* buf = ans.c_str();
|
||||||
CHECK_WSTR(buf, L"0x1.000p+1");
|
CHECK_WSTR(buf, L"0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(0);
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD defaultfloat << 1.5;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD scientific << 2.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2e+00");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD hexfloat << 2.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-1);
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD defaultfloat << 1.5;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.5");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.000000");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD scientific << 2.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2.000000e+00");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD hexfloat << 2.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-49);
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.000000");
|
||||||
|
|
||||||
|
outs.precision(3);
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD defaultfloat << 1.5L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.5");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.000");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD scientific << 2.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2.000e+00");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD hexfloat << 2.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(0);
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD defaultfloat << 1.5L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD scientific << 2.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2e+00");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD hexfloat << 2.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-1);
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD defaultfloat << 1.5L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.5");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.000000");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD scientific << 2.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"2.000000e+00");
|
||||||
|
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD hexfloat << 2.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1");
|
||||||
|
|
||||||
|
outs.precision(-49);
|
||||||
|
outs.str(L"");
|
||||||
|
outs << STD fixed << 1.0L;
|
||||||
|
CHECK_WSTR(outs.str().c_str(), L"1.000000");
|
||||||
|
|
||||||
// test Boolx inserter
|
// test Boolx inserter
|
||||||
const Boolx no(0), yes(1);
|
const Boolx no(0), yes(1);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче