зеркало из 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
|
||||
#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
|
||||
template <class _Elem, class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem>>>
|
||||
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
|
||||
string _Buf;
|
||||
char _Fmt[8];
|
||||
bool _Isfixed = (_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed;
|
||||
streamsize _Precision = _Iosbase.precision() <= 0 && !_Isfixed ? 6 : _Iosbase.precision(); // desired precision
|
||||
size_t _Bufsize = static_cast<size_t>(_Precision);
|
||||
if (_Isfixed && 1e10 < _CSTD fabs(_Val)) { // f or F format
|
||||
const auto _Float_flags = _Iosbase.flags() & ios_base::floatfield;
|
||||
const bool _Is_fixed = _Float_flags == ios_base::fixed;
|
||||
const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific);
|
||||
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;
|
||||
(void) _CSTD frexp(_Val, &_Ptwo);
|
||||
_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
|
||||
string _Buf;
|
||||
char _Fmt[8];
|
||||
bool _Isfixed = (_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed;
|
||||
streamsize _Precision = _Iosbase.precision() <= 0 && !_Isfixed ? 6 : _Iosbase.precision(); // desired precision
|
||||
size_t _Bufsize = static_cast<size_t>(_Precision);
|
||||
if (_Isfixed && 1e10 < _CSTD fabsl(_Val)) { // f or F format
|
||||
const auto _Float_flags = _Iosbase.flags() & ios_base::floatfield;
|
||||
const bool _Is_fixed = _Float_flags == ios_base::fixed;
|
||||
const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific);
|
||||
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;
|
||||
(void) _CSTD frexpl(_Val, &_Ptwo);
|
||||
_Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L;
|
||||
|
|
|
@ -213,9 +213,109 @@ void test_main() { // test basic workings of ostream definitions
|
|||
outs << STD hexfloat << 2.0;
|
||||
STD string ans = outs.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
|
||||
const Boolx no(0), yes(1);
|
||||
outs.str("");
|
||||
|
|
|
@ -208,7 +208,107 @@ void test_main() { // test basic workings of ostream definitions
|
|||
outs << STD hexfloat << 2.0;
|
||||
STD wstring ans = outs.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
|
||||
const Boolx no(0), yes(1);
|
||||
|
|
Загрузка…
Ссылка в новой задаче