-4

I want to use atof to convert my string to a double,the answer is correct ,but not very accurate

ATTENTION: because of some other reasons, fscanf is not permitted

my code is :

#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;
 }

my file : lstm_txt is :

4.217959344387054443e-01 -2.566376626491546631e-01 2.173236161470413208e-01 4.217959344387054443e-01

code hasn't bug, and the result is :

 lstm_weight: 4.217959344387054443e-01
 convert "lstm_weight" to lstm_val is : 0.421796

but I want Istm_val is 0.4217959344387054443 ,how can I do that?

KatrinaKing
  • 43
  • 2
  • 6
  • 1) You're not getting 18 decimal digits of precision from a `double` on current architectures. You could try `long double` instead. 2) Read the manpage for `printf()`. – EOF Dec 22 '20 at 00:40
  • 1
    atof takes in a float not a double – TruVortex_07 Dec 22 '20 at 00:40
  • `fscanf is not permitted` but why? it's a standard function and is available everywhere. The `ato*` family can invoke UB so they shouldn't be used. [*"If the converted value falls out of range of the return type, the return value is undefined"*](https://en.cppreference.com/w/c/string/byte/atof). See the reason [why `atoi()` shouldn't be used](https://stackoverflow.com/q/17710018/995714). The correct way to convert is [`strtof, strtod, strtold`](https://en.cppreference.com/w/c/string/byte/strtof) – phuclv Dec 22 '20 at 00:52
  • @phuclv The `scanf` functions have the same defect in their specification and shouldn't be used either. – zwol Dec 22 '20 at 00:54
  • 1
    @TruVortex_07 who said that? `atof` takes in a `char*` the represents a `double`. Did you read the [doc](https://en.cppreference.com/w/c/string/byte/atof)? – phuclv Dec 22 '20 at 00:54
  • @zwol I already suggested `strod` above – phuclv Dec 22 '20 at 00:54
  • @phuclv http://www.cplusplus.com/reference/cstdlib/atof/?kw=atof, it says the parameters are a C-string beginning with the representation of a floating-point number. however i'm not really familiar with atof because i usually code in java or c++ – TruVortex_07 Dec 22 '20 at 00:58
  • @TruVortex_07 cplusplus.com is notoriously wrong and shouldn't be used. You can find lots of people pointing out that on SO. cppreference.com is maintained by professionals and is far more correct – phuclv Dec 22 '20 at 01:02
  • @phuclv I was responding to your 'why isn't fscanf permitted?' query. I don't know why it's not permitted for OP, but all of the `*scanf` functions are forbidden in every code base where I have anything to say about it, for the reason I gave (and several others, e.g. `scanf("%s", buffer)` is just as dangerous as `gets`). – zwol Dec 22 '20 at 15:01

3 Answers3

1

you could try something like sprintf() here's an example:

#include <stdio.h>

int main() {
    char str[50];
    double n = 0.3984092590879;
    sprintf(str, "%lf", n);
    printf(str);
    return 0;
}

prints out:

0.3984092590879
TruVortex_07
  • 280
  • 1
  • 3
  • 16
  • there's no difference in printing with `sprintf` or `printf` or any functions in the `printf` family, the output is the same with the same format specifier. And there's no way to store more precisions than double is able to store – phuclv Dec 22 '20 at 01:09
  • 1
    well he wanted a way to convert his double to string so and thats what he got – TruVortex_07 Dec 22 '20 at 01:10
0

A double typically has about 15 digits of decimal precision. You will not get more accuracy than that if you store the value in a double. You are getting less because you didn't tell printf how many digits of precision to use for output, so you got the default.

Use something like %0.15f instead of %f.

convert "lstm_weight" to lstm_val is : 0.421795934438705

With %0.20f, I get:

convert "lstm_weight" to lstm_val is : 0.42179593443870544434

That's the best you'll do with a double.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
0

Printing %.17f you can have a precision up to 0.42179593443870544

    printf("\n convert \"lstm_weight\" to lstm_val is : %.17f\n\n", lstm_val);

Matteo Pinna
  • 409
  • 4
  • 9