2016-10-06 3 views
2

Я читаю поплавки из строки. Они могут быть написаны в различной форме, такЯвляется ли stof, strtof детерминированным?

float f1 = strtof("999999999999.16"); 
float f2 = stof("000999999999999.1600000"); 
assert(f1 == f2); 

Могу ли я быть уверен, что утверждение будет всегда верно, независимо от начальных и конечных нулей? Сепаратор всегда будет точкой, stof не обрабатывает запятую.

+0

Не уверен на 100%. 'stof' вызывает' strtod' внутри, поэтому я не знаю, будет ли это иметь значение или нет. В C++ 17 он будет называть 'strtof' внутренне, поэтому он должен быть гарантирован. – NathanOliver

+0

Я тоже не уверен на 100%. Я думаю, что этот вопрос требует ссылки на стандарты. Ответ @SnoopDog, поскольку он стоит, должен рассматриваться как нечто большее, чем предположение. – Bathsheba

ответ

2

The C11 standard, in 7.22.1.3p9, это сказать о Кассиопеяне strtof/strtod/strtold (которые должны быть какие версии C++ использовать под, по крайней мере, судя по cppreference):

Если испытуемый последовательность имеет десятичную форму и не более DECIMAL_DIG (определено в <float.h>) значащие цифры, результат должен быть правильно округлен.

Учитывая, что оба ваших строк кода имеют одинаковое число значащих цифр, то они должны вести себя так же. Но это всего лишь гипотеза, основанная на том факте, что в стандарте здесь вообще упоминаются «значащие цифры»; он нигде не упоминается, и стандарт не говорит ничего более явного о том, что касается ведущей (до десятичной точки) или конечной (после десятичной точки) нулей.

+0

Вы уверены, что оба используют 'strtof'? cplusplus упоминает 'stof', используя' strtod', но ничего не похоже на 'stof' – user463035818

+0

@ tobi303 [cppreference] (http: //en.cppreference.com/w/cpp/string/basic_string/stof) упоминает 'strtof' как« _underlying function_ »(в сноске, но не имеет лучшей ссылки). – mindriot

+0

@mindriot 'stof' вызывает' strtod' до C++ 17, где он будет называть 'strtof'. – NathanOliver

1

В C++ 14 (§21.5) стандартные гласит:

float stof(const string& str, size_t* idx = 0);

double stod(const string& str, size_t* idx = 0);

long double stold(const string& str, size_t* idx = 0);

эффекты: первые две функции называют strtod(str.c_str(), ptr) и третья функция вызывает strtold(str.c_str(), ptr) , Каждая функция возвращает преобразованный результат, если таковой имеется. Аргумент ptr обозначает указатель на объект, внутренний для функции, который используется для определения того, что хранить в *idx. Если функция не генерирует исключение и idx != 0, функция сохраняет в *idx индекс первого неотвержденного элемента str.

Во многих случаях, следовательно, они будут такими же, но промежуточный double действительно открывает потенциал для double rounding. Например. если str = "1.0000000596046448", то ближайший float (при условии, IEEE754 арифметического) является 1.0000001f, в то время как ближайший double точно на полпути между 1.0f и 1.0000001f, так и последующим превращением в float будет округлить до 1.0f.

Это, по крайней мере, теория. На практике, однако, я не могу воссоздать это: http://ideone.com/NMRy14

Смежные вопросы