Глядя на документацию для strtod
:
Linux:
Бесконечность — это либо «INF», либо «INFINITY», независимо от регистра.
OS X:
Если часть строки следует за дополнительным плюсом
или знак минус начинается с «INFINITY» … это
интерпретируется как бесконечность
Я использую stringstream
преобразовать string
к double
и (ошибочно) предположил, что strtod
использовался за кулисами. Ни clang ++ 3.4, ни g ++ 4.8 не преобразуют «INFINITY» в inf
, Только clang ++, кажется, конвертирует «INF» inf
,
Я предполагаю слишком много о работе stringstream
«s operator>>
? Или, может быть, я не могу проверить важное состояние ошибки? Мой тестовый код ниже (g++ -std=c++11 -Wall -Wextra inf.cpp -o inf
).
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
void
doTest(
const std::string &str)
{
double val1 = std::strtod(str.c_str(), nullptr);
std::cout << str << " - std::isinf from strtod: " << std::boolalpha <<
std::isinf(val1) << '\n';
std::stringstream sstream(str);
double val2;
sstream >> val2;
std::cout << str << " - std::isinf from stringstream: " <<
std::boolalpha << std::isinf(val2) << '\n';
std::cout << val1 << " vs " << val2 << '\n';
std::cout << std::endl;
}
int
main()
{
doTest("INFINITY");
doTest("+INF");
return (0);
}
clang ++ 3.4 (OS X 10.9.2):
INFINITY - std::isinf from strtod: true
INFINITY - std::isinf from stringstream: false
inf vs 0
+INF - std::isinf from strtod: true
+INF - std::isinf from stringstream: true
inf vs inf
g ++ 4.8:
INFINITY - std::isinf from strtod: true
INFINITY - std::isinf from stringstream: false
inf vs 0
+INF - std::isinf from strtod: true
+INF - std::isinf from stringstream: false
inf vs 0
Я прошел через стандарт, и оператор потока должен быть определен в терминах функции C strtod
, но только после фильтрации чего-либо, что может стать не-числом или бесконечностью на этапе 2.
После следа документа:
27.7.2.2.2 Арифметические экстракторы
Как и в случае со вставками, эти экстракторы зависят от num_get локали<> (22.4.2.1) объект
выполнить синтаксический анализ данных входного потока. Эти экстракторы ведут себя как отформатированные функции ввода (как
описано в 27.7.2.2.1). После того, как часовой объект построен, преобразование происходит так, как если бы оно выполнялось
следующий фрагмент кода:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
22.4.2.1.2 виртуальные функции num_get
Этап 2: Если
in==end
затем этап 2 заканчивается. В противном случае charT берется из in и локальных переменных.
инициализируются как будто
char_type ct = *in;
char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms];
if (ct == use_facet<numpunct<charT> >(loc).decimal_point())
c = ’.’;
bool discard = ct == use_facet<numpunct<charT> >(loc).thousands_sep()
&& use_facet<numpunct<charT> >(loc).grouping().length() != 0
где значения src и атомов определены как если бы:
static const char src[] = "0123456789abcdefxABCDEFX+-";
char_type atoms[sizeof(src)];
use_facet<ctype<charT> >(loc).widen(src, src + sizeof(src), atoms);
для этого значения loc.