Я хочу использовать atof для преобразования моей строки в двойную, ответ правильный, но не очень точный
ВНИМАНИЕ: по некоторым другим причинам fscanf не разрешен
мой код:
#include <stdio.h>
#include <stdlib.h>
#define MAXCN 50
int main(void)
{ FILE* lstm_txt = NULL;
char lstm_weight[MAXCN] = {0};
int lstm = 0;
int i = 0;
float lstm_val;
if ((lstm_txt = fopen("test1.txt", "r"))== NULL){
fprintf(stderr,"error:file open failed 'test1.txt'.\n");
return 1;
}
while ((i + 1 < MAXCN) && ((lstm = fgetc(lstm_txt)) != ' ' ) && (lstm != EOF)){
lstm_weight[i++] = lstm;
}
//lstm_weight[i] = 0;
printf("\n lstm_weight: %s\n\n", lstm_weight);
lstm_val = atof(lstm_weight);
printf("\n convert \"lstm_weight\" to lstm_val is : %f\n\n", lstm_val);
return 0;
}
мой файл: lstm_txt:
4.217959344387054443e-01 -2.566376626491546631e-01 2.173236161470413208e-01 4.217959344387054443e-01
код не содержит ошибок, и результат:
lstm_weight: 4.217959344387054443e-01
convert "lstm_weight" to lstm_val is : 0.421796
но я хочу, чтобы Istm_val был 0,4217959344387054443, как я могу это сделать?
atof принимает поплавок, а не двойной
fscanf is not permitted
но почему? это стандартная функция и доступна везде. Семейство ato*
может вызывать UB, поэтому их не следует использовать. «Если преобразованное значение выходит за пределы диапазона возвращаемого типа, возвращаемое значение не определено» . Посмотрите, почему не следует использовать atoi() . Правильный способ преобразования: strtof, strtod, strtold@phuclv Функции scanf
имеют тот же дефект в своей спецификации, и их также не следует использовать.
@TruVortex_07 кто это сказал? atof
принимает char*
и представляет double
. Вы читали документ?
@zwol я уже предложил strod
выше
@phuclv cplusplus.com/reference/cstdlib/atof/?kw=atof, там сказано, что параметры представляют собой C-строку, начинающуюся с представления числа с плавающей запятой. однако я не совсем знаком с atof, потому что я обычно кодирую на java или c++
@TruVortex_07 cplusplus.com общеизвестно ошибочен и не должен использоваться. Вы можете найти много людей, указывающих на это на SO. cppreference.com поддерживается профессионалами и является гораздо более правильным
@phuclv Я отвечал на ваш вопрос «почему fscanf не разрешен?» запрос. Я не знаю, почему это не разрешено для OP, но все функции *scanf
запрещены в каждой кодовой базе, где мне есть что сказать об этом, по причине, которую я привел (и несколько других, например, scanf("%s", buffer)
так же опасен, как и gets
).
double
обычно имеет около 15 знаков после запятой. Вы не получите большей точности, если сохраните значение в двойном значении. Вы получаете меньше, потому что вы не сказали printf
, сколько цифр точности использовать для вывода, поэтому вы получили значение по умолчанию.
Используйте что-то вроде %0.15f
вместо %f
.
преобразовать «lstm_weight» в lstm_val: 0,421795934438705
С %0.20f
я получаю:
преобразовать «lstm_weight» в lstm_val: 0,42179593443870544434
Это лучшее, что вы можете сделать с double
.
Печать %.17f
вы можете иметь точность до 0.42179593443870544
printf("\n convert \"lstm_weight\" to lstm_val is : %.17f\n\n", lstm_val);
вы можете попробовать что-то вроде sprintf()
вот пример:
#include <stdio.h>
int main() {
char str[50];
double n = 0.3984092590879;
sprintf(str, "%lf", n);
printf(str);
return 0;
}
распечатывает:
0.3984092590879
нет никакой разницы в печати с помощью sprintf
или printf
или любых функций семейства printf
, вывод будет таким же с одним и тем же спецификатором формата. И нет способа сохранить больше точности, чем может хранить double
ну, он хотел найти способ преобразовать свой двойник в строку, и вот что он получил
1) Вы не получаете 18 десятичных цифр точности от
double
на текущих архитектурах. Вместо этого вы можете попробоватьlong double
. 2) Прочтите справочную страницу дляprintf()
.