как сделать пользовательскую реализацию atof () более «правильной»?
Легко: 1) никогда не переполнять промежуточные вычисления и 2) только округлять один раз (в конце).
Это сложно , чтобы сделать эти 2 шага.
Примечание: C's atof()
, strtof()
и т. Д. Также обрабатывают экспоненциальную запись - в десятичной и шестнадцатеричной форме.
Потенциальные округления
val*10
(val*10)+(c-'0');
pow(10,j)
val*pow(10,j) // This last multiplication is the only tolerable one.
Потенциальное переполнение (даже если окончательный ответ находится в пределах диапазона)
val*10
(val*10)+(c-'0');
pow(10,j)
Использование более широкого типа, например double
, можетзначительно уменьшить возникновение таких проблем и добиться более «правильного» ОП. Тем не менее, они все еще существуют.
Это не простая задача , которую нужно решить, чтобы получить лучший (правильный) результат с плавающей запятой из всех строковых входных данных.
Пример подходов к решению.
Избегайте переполнения: вместо pow(10,j)
:
val = val*pow(5,j); // rounds, `pow(5,j)` not expected to overflow a finite final result.
val = val*pow(2,j); // Does not round except at extremes
Код должен сформироваться (ival*10)+(c-'0')
с использованием расширенной целочисленной математики в цикле для точности.
Все же это простоРассказывая о многих угловых случаях.
@ Eric Postpischil прокомментировал надежный код C ++, который хорошо обрабатывает неэкспоненциальный ввод строки записи.Это делает начальную математику, используя целые числа и только раунды позже в процессе.Этот связанный код не виден, если ваш представитель не более 10 000+, поскольку вопрос был удален.