strtod - Dynamic Memory?

M

Marky C

atof is not working.

double a = atof("12.345");

a gets set to 12.000

I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

All thoughts gratefully received

Marky C
 
R

Richard Bos

atof is not working.

double a = atof("12.345");

a gets set to 12.000

That is not allowed, surely? 12.345 must be representable, albeit
possibly with a slight error, within a double. "12.345" is a valid
string representation of 12.345. Therefore, atof() _must_ convert
"12.345" to (double)12.345 plus-or-minus a slight error, which error is
certainly smaller than two decimals.
I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

The latter should be immaterial, but are you sure that this is a
complete hosted ISO C implementation, and not a freestanding one, or
even a non-ISO version?
Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

Shouldn't be.

Richard
 
L

Leor Zolman

atof is not working.

double a = atof("12.345");

a gets set to 12.000

I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

That's difficult to imagine. Are you sure you've included the appropriate
header file (math.h or stdlib.h)? If you'd have gotten 0 or some totally
random number instead of 12 into a, then forgetting to include the header
would have been a lot higher on my probability chart. But it is still a
possibility.

If that doesn't fix it, you may need to locate a group that knows more
specifics about your platform.
-leor
 
T

Thomas Stegen

Marky said:
atof is not working.

double a = atof("12.345");

a gets set to 12.000

If you forget to include a prototype for atof it will
default to return int and as we all know
(double)(int)12.345 == 12.000 or thereabouts.

Have you included stdlib.h?
 
D

Dan Pop

In said:
atof is not working.

double a = atof("12.345");

a gets set to 12.000

Did you consider including said:
I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

Nope. Show us a complete program illustrating your problem.

Dan
 
M

Mike Wahler

Marky C said:
atof is not working.

double a = atof("12.345");

a gets set to 12.000

If you're using a pre-C99 compiler, and failed
to provide a prototype for 'atof()' (by #including
<stdlib.h>), then the compiler will assume that 'atof()'
returns type 'int'. This fact will truncate the
fractional part of the return value before assigning
it to 'a'. If using a C99 compiler without providing
the prototype, you should have received a diagnostic.
I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

That shouldn't matter, as long as you're using a conforming
hosted implemenatation.
Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

Perhaps, but I doubt it.
All thoughts gratefully received

-Mike
 
P

Peter Slootweg

Marky C said:
atof is not working.

double a = atof("12.345");

a gets set to 12.000

I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

All thoughts gratefully received

Marky C

First I'd check what everyone else suggested
i.e. did you include stdlib.h?
If you did then I'd confirm the locale you are using has '.' as the decimal
point

try the following ( assuming printf actually displays something on your
system)
#include <locale.h>
#include <stdio.h>

void PrintLocaleDecimal(void)
{
struct lconv *lcp = localeconv();

printf("decimal='%s'\n",
lcp->decimal_point);
}
 
F

Fred L. Kleinschmidt

Marky said:
atof is not working.

double a = atof("12.345");

a gets set to 12.000

I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

All thoughts gratefully received

Marky C

Did you #include <stdlib.h> ? If not, your compiler thinks the result of
the atof call is an int.
 
D

Dan Pop

In said:
That's difficult to imagine. Are you sure you've included the appropriate
header file (math.h or stdlib.h)? If you'd have gotten 0 or some totally

It's <stdlib.h> *only*. A <math.h> declaring atof would be broken.

Dan
 
M

Malcolm

Mike Wahler said:
If you're using a pre-C99 compiler, and failed
to provide a prototype for 'atof()' (by #including
<stdlib.h>), then the compiler will assume that 'atof()'
returns type 'int'. This fact will truncate the
fractional part of the return value before assigning
it to 'a'.
That's not what normally happens. Generally the compiler interprets the
double as an integer, either grabbing bytes from the stack or reading from
the register used for integer returns, with garbage results.
 
D

Dan Pop

If you're using a pre-C99 compiler, and failed
to provide a prototype for 'atof()' (by #including
<stdlib.h>), then the compiler will assume that 'atof()'
returns type 'int'. This fact will truncate the
fractional part of the return value before assigning
it to 'a'.

Think harder. If atof is supposed to return an int, the compiler
will look in the wrong place for the result (e.g. an integer register
instead of a floating point register), or will interpret part of
the representation of the f.p. result as an integer, if the result
is passed in memory (on the stack). No conversion of 12.345 to the
implicitly declared type of atof() is supposed to take place.
A result of 12 can only be explained as a pure accident (and I have
no better explanation).

Dan
 
M

Martin Ambuhl

Marky said:
atof is not working.

Maybe, but more likely your code is wrong.
double a = atof("12.345");
a gets set to 12.000

This suggest atof is returning an int, which would be the default
assumption if atof were not prototyped. This suggests that you forgot
to #include said:
I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.
Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

All that should be irrelevant.
All thoughts gratefully received

Cut and paste the following _exactly_. Report your findings.

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
double a = atof("12.345");
double b = strtod("12.345", 0);
printf("a = %g, b = %g\n", a, b);
return 0;
}

[output should be]
a = 12.345, b = 12.345
 
M

Mike Wahler

Dan Pop said:
In <[email protected]> "Mike Wahler"

Think harder.

That's too hard. :)
If atof is supposed to return an int, the compiler
will look in the wrong place for the result (e.g. an integer register
instead of a floating point register), or will interpret part of
the representation of the f.p. result as an integer, if the result
is passed in memory (on the stack). No conversion of 12.345 to the
implicitly declared type of atof() is supposed to take place.
A result of 12 can only be explained as a pure accident (and I have
no better explanation).

You're right, I didn't give the issue enough thought.
I'll blame it on the (unseasonably) nice weather here
today, which has me frequently looking out the window. :)

-Mike
 
D

David Resnick

atof is not working.

double a = atof("12.345");

a gets set to 12.000

I am working on a toshiba micro. The data map has no space allocated
to it for dynamic memory.

Does anyone have an idea? Could it be due to the lack of dynamic
memmor space?

All thoughts gratefully received

Marky C

Perhaps your program is not running in the "C" locale. In which case the
character that represents the decimal point depends on the locale. As
far as I know, it is always either a '.' or a ',', but that isn't
guaranteed. Example that demonstrates the issue using strtod, which
is preferable to atof:

dresnick(3276)$ cat foo.c
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
printf("%g\n", strtod("12.345", NULL));
setlocale(LC_NUMERIC, "de_DE");
printf("%g\n", strtod("12.345", NULL));
printf("%g\n", strtod("12,345", NULL));
return 0;
}
dresnick(3277)$ gcc -Wall -ansi -pedantic -o foo foo.c
dresnick(3278)$ foo
12.345
12
12,345


-David
 
D

Dan Pop

In said:
Perhaps your program is not running in the "C" locale. In which case the
character that represents the decimal point depends on the locale.

Nope:

6 In other than the "C" locale, additional locale-specific subject
^^^^^^^^^^
sequence forms may be accepted.

This means that '.' is accepted in ALL locales, but other locales can also
accept other characters as the "decimal point".
As far as I know, it is always either a '.' or a ',', but that isn't
guaranteed. Example that demonstrates the issue using strtod, which
is preferable to atof:

dresnick(3276)$ cat foo.c
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
printf("%g\n", strtod("12.345", NULL));
setlocale(LC_NUMERIC, "de_DE");
printf("%g\n", strtod("12.345", NULL));
printf("%g\n", strtod("12,345", NULL));
return 0;
}
dresnick(3277)$ gcc -Wall -ansi -pedantic -o foo foo.c
dresnick(3278)$ foo
12.345
12
12,345

Your library is broken in multiple places. The correct output of your
program consists of three *identical* lines because "12.345" is valid
input for strtod in *any* locale and because the current locale does
NOT affect the output of the %g conversion specifier (for reasons
that I do not understand, the Single Unix Specification is at odds
with the C standard here).

Dan
 
D

Dan Pop

In said:
If you forget to include a prototype for atof it will
default to return int and as we all know
(double)(int)12.345 == 12.000 or thereabouts.

So what? There is no (double)(int)12.345 taking place in this code,
if the implicit declaration of atof is in effect.

BTW, there is no need for a prototype to fix the code, a good old
declaration is enough:

double atof();

But, of course, the *right* fix is to include <stdlib.h>.

Dan
 
K

Keith Thompson

In <[email protected]>
(e-mail address removed) (David Resnick) writes: [...]
Perhaps your program is not running in the "C" locale. In which case the
character that represents the decimal point depends on the locale.

Nope:

6 In other than the "C" locale, additional locale-specific subject
^^^^^^^^^^
sequence forms may be accepted.

This means that '.' is accepted in ALL locales, but other locales can also
accept other characters as the "decimal point".

No, I don't think it does.

The standard defines the atof function as (nearly) equivalent to a
call to the strtod function.

The description of the strtod function (C99 7.20.1.3) says:

The expected form of the subject sequence is an optional plus or
minus sign, then one of the following:

-- a nonempty sequence of decimal digits optionally containing
a decimal-point character, then an optional exponent part
as defined in 6.4.4.2;

It uses the term "decimal-point character", not "period". A few
paragraphs later, it says:

If the subject sequence has the expected form for a floating-point
number, the sequence of characters starting with the first digit
or the decimal-point character (whichever occurs first) is
interpreted as a floating constant according to the rules of
6.4.4.2, except that the decimal-point character is used in place
of a period, [...]

(The wording in the C90 standard is similar; it's easier to
cut-and-paste from my copy of the C99 standard.)
Your library is broken in multiple places. The correct output of your
program consists of three *identical* lines because "12.345" is valid
input for strtod in *any* locale and because the current locale does
NOT affect the output of the %g conversion specifier (for reasons
that I do not understand, the Single Unix Specification is at odds
with the C standard here).

The description of the %e and %f conversion specifiers also uses the
term "decimal-point character", not "period". ("%g" is defined in
terms of "%e" and "%f".)

C99 7.1.1p2 says (underscores indicate italics):

The _decimal-point character_ is the character used by functions
that convert floating-point numbers to or from character sequences
to denote the beginning of the fractional part of such character
sequences. It is represented in the text and examples by a
period, but may be changed by the setlocale function.

Again, the wording in the C90 standard is similar.

For locales other than "C", the numeric conversion functions and
formatted I/O functions are not required to recognize '.' as a
decimal-point character.
 
D

David Resnick

Nope:

6 In other than the "C" locale, additional locale-specific subject
^^^^^^^^^^
sequence forms may be accepted.

This means that '.' is accepted in ALL locales, but other locales can also
accept other characters as the "decimal point".


Your library is broken in multiple places. The correct output of your
program consists of three *identical* lines because "12.345" is valid
input for strtod in *any* locale and because the current locale does
NOT affect the output of the %g conversion specifier (for reasons
that I do not understand, the Single Unix Specification is at odds
with the C standard here).

Dan


Well, the library (glibc) is behaving as documented for the library.
Guess it isn't conforming to the C-standard. Admittedly, I do have an
older glibc (not sure the version, I'm not at work now). The glibc
docs for strtod say:

....
A floating point number in decimal or hexadecimal format. The decimal
format is:

* A nonempty sequence of digits optionally containing a
decimal-point character--normally ., but it depends on the locale (see
General Numeric).
....

I see that N869 says this isn't correct. The standard says that
strtod needs to take a floating point constant as described by section
6.4.4.2, which does explicitly have the '.' character. And as you
say, locale setting can give it an additional options.

That said, the original poster's issue could be due to a similar
(perhaps the same?) broken library implementation.

-David
 
K

Keith Thompson

Well, the library (glibc) is behaving as documented for the library.
Guess it isn't conforming to the C-standard. Admittedly, I do have an
older glibc (not sure the version, I'm not at work now). The glibc
docs for strtod say:

...
A floating point number in decimal or hexadecimal format. The decimal
format is:

* A nonempty sequence of digits optionally containing a
decimal-point character--normally ., but it depends on the locale (see
General Numeric).
...

I see that N869 says this isn't correct. The standard says that
strtod needs to take a floating point constant as described by section
6.4.4.2, which does explicitly have the '.' character. And as you
say, locale setting can give it an additional options.

I think you're misreading N869. It says:

The expected form of the subject sequence is an optional plus or
minus sign, then one of the following:

-- a nonempty sequence of decimal digits optionally containing
a decimal-point character, then an optional exponent part
as defined in 6.4.4.2;

The phrase "as defined in 6.4.4.2" refers only to the optional
exponent part, not to the entire floating point costant. The fact
that it uses the term "decimal-point character" rather than "period"
makes it clear that it doesn't have to recognize a period. The term
"decimal-point character" is defined in 7.1.1p3:

The _decimal-point character_ is the character used by functions
that convert floating-point numbers to or from character sequences
to denote the beginning of the fractional part of such character
sequences. It is represented in the text and examples by a period,
but may be changed by the setlocale function.

The actual C99 standard has identical wording; the wording in the C90
standard is identical or very similar.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top