79 lines
2.4 KiB
C
79 lines
2.4 KiB
C
/*
|
||
Exercise 4-2. Extend atof to handle scientific notation of the form
|
||
123.45e-6, where a floating-point number may be followed by e or E and an
|
||
optionally signed exponent.
|
||
|
||
- "123.45e-6" → это означает 123.45 × 10⁻⁶ = 0.00012345
|
||
- "2.5e3" → это означает 2.5 × 10³ = 2500.0
|
||
- "1.23E+2" → это означает 1.23 × 10² = 123.0
|
||
- "5e-2" → это означает 5 × 10⁻² = 0.05
|
||
|
||
Формат научной нотации:
|
||
|
||
[число][e или E][необязательный знак +/-][показатель степени]
|
||
|
||
То есть после основного числа (которое твоя функция уже умеет парсить) может
|
||
идти:
|
||
1. Символ 'e' или 'E'
|
||
2. Необязательный знак '+' или '-'
|
||
3. Целое число (показатель степени десятки)
|
||
|
||
*/
|
||
|
||
#include <ctype.h>
|
||
double atof(char s[]) {
|
||
double val, power;
|
||
int i, sign;
|
||
// Идем до первого "не пробела"
|
||
for (i = 0; isspace(s[i]); i++)
|
||
;
|
||
// Если "-" то будем умножать на -1
|
||
sign = (s[i] == '-') ? -1 : 1;
|
||
// Если вдруг после получения знака опять идут + и - то скипаем их
|
||
if (s[i] == '+' || s[i] == '-')
|
||
i++;
|
||
/*
|
||
* Допустим у нас число 123.298
|
||
* Смотрим шаги по очереди:
|
||
* 1
|
||
* val = 10.0 * 0 + ('1' - '0') = 0 + (50 - 49) = 0 + 1 = 1
|
||
* 2
|
||
* val = 10.0 * 1 + ('2' - '0') = 1 + (51 - 49) = 10.0 + 2 = 12.0
|
||
* 3
|
||
* val = 10.0 * 12.0 + ('3' - '0') = 120.0 + (52 - 49) = 120.0 + 3 = 123.0
|
||
*/
|
||
for (val = 0.0; isdigit(s[i]); i++)
|
||
val = 10.0 * val + (s[i] - '0');
|
||
// Скипаем точку
|
||
if (s[i] == '.')
|
||
i++;
|
||
/*
|
||
* 0 49
|
||
* 1 50
|
||
* 2 51
|
||
* 3 52
|
||
* 4 53
|
||
* 5 54
|
||
* 6 55
|
||
* 7 56
|
||
* 8 57
|
||
* 9 58
|
||
* |
|
||
* Продолжаем с 123.298
|
||
* 2
|
||
* val=10.0*123.0+(s[i]-'0') = 1230.0+(51-49) = 1230.0+2 = 1232.0
|
||
* power = power * 10 = 1.0*10 = 10.0
|
||
* 9
|
||
* val=10.0*1232.0+(s[i]-'0')=12320.0+(58-49)=12329.0
|
||
* power = power * 10 = 10.0*10 = 100.0
|
||
* 8
|
||
* val=10.0*12329.0+(s[i]-'0')=123290.0+(57-49)=123298.0
|
||
* power = power * 10 = 100.0*10 = 1000.0
|
||
*/
|
||
for (power = 1.0; isdigit(s[i]); i++) {
|
||
val = 10.0 * val + (s[i] - '0');
|
||
power *= 10;
|
||
}
|
||
// 1 * (123289.0/1000) = 123.289
|
||
return sign * val / power;
|
||
}
|