By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,669 Members | 1,634 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,669 IT Pros & Developers. It's quick & easy.

atof equivalent for long double in standard ANSI C?

P: n/a
Greetings again,

I will burden the group with yet another tenderfoot question, but since
conscientious googling hasn't yield a lucid answer I thought I would
risk the shortcut of asking here since I am so very keen to learn to
code in standard C.

Could someone tell me the long double equivalent of atof()? I was
getting some peculiar behaviour in a little bit of math code I am
working with. I thought the problem was in the math algorithms, but not
so--it is the input interface. I get my desired numeric input with
gets(), put it to a character string txt, and put it into a long double
variable x with x = atof(x).

But a little testing as revealed that when the string txt actually
represents a numeral outside of the double range, atof() translates it
not to its long double equivalent, but inf. For example the entered
text string 1e500 is not converted to the long double quantity
1.0E500L, but, as I said, inf.

What is the appropriate ANSI C approach to this? I am aware of
non-standard functions such as atold() or _atold() in other compilers,
but I want to be good boy and speak standard C.

Many thanks for your patient assistance.

Les

Aug 9 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
"lcw1964" <le***********@alumni.uwo.cawrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
: Greetings again,
:
: I will burden the group with yet another tenderfoot question, but since
: conscientious googling hasn't yield a lucid answer I thought I would
: risk the shortcut of asking here since I am so very keen to learn to
: code in standard C.
:
: Could someone tell me the long double equivalent of atof()? I was
: getting some peculiar behaviour in a little bit of math code I am
: working with. I thought the problem was in the math algorithms, but not
: so--it is the input interface. I get my desired numeric input with
: gets(), put it to a character string txt, and put it into a long double
: variable x with x = atof(x).

In my draft copy of the C99 standard, there is no long-double
equivalent of atof.
But there is an equivalent of the safer strtod:
long double strtold(const char* nptr, char** endptr);
As this actually provides a safer interface (error-checking),
the omission of the less safe alternative might have been
made on purpose...
hth -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Aug 9 '06 #2

P: n/a
"lcw1964" <le***********@alumni.uwo.cawrote:
I will burden the group with yet another tenderfoot question, but since
conscientious googling hasn't yield a lucid answer I thought I would
risk the shortcut of asking here since I am so very keen to learn to
code in standard C.

Could someone tell me the long double equivalent of atof()?
There isn't one. atof() is not the best function for the job, anyway,
because it has undefined behaviour on overflow. It is safe _if_ you know
that the string you pass it will always contain a floating point number
that fits in a float. In the general case, though, it's better to use
strtof(), or for long double, strtold(). Unfortunately both of those are
C99 only. C89 has just strtod(), and no function to convert to long
double.
I get my desired numeric input with gets(),
This is a function to avoid under all circumstances. It cannot be told
how many characters to read, so it is impossible to stop it from
scribbling over the end of its buffer - with potentially disastrous
consequences - without the use of OS-specific functions, and for any
colleague who might pass by, leatherware of a kind that is illegal to
sell in several of the States of the USA.

Use fgets() instead.
But a little testing as revealed that when the string txt actually
represents a numeral outside of the double range, atof() translates it
not to its long double equivalent, but inf.
You're lucky. It's allowed to bomb.

Richard
Aug 9 '06 #3

P: n/a
Use sscanf() instead.
It's a lot better to boot.
Aug 9 '06 #4

P: n/a
"Dann Corbit" <dc*****@connx.comwrites:
Use sscanf() instead.
It's a lot better to boot.
Instead of what? Please provide context.

sscanf() invokes undefined behavior if the input string cannot be
represented in the specified type.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 9 '06 #5

P: n/a
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"Dann Corbit" <dc*****@connx.comwrites:
>Use sscanf() instead.
It's a lot better to boot.

Instead of what? Please provide context.

sscanf() invokes undefined behavior if the input string cannot be
represented in the specified type.
Good point. Maybe something like this could be used as a starting point.
It's not very robust for error checking, but it could easily be improved to
a useful state.

#include <stdlib.h>
#include <float.h>

typedef enum {FALSE=0,TRUE=1} BOOL;

BOOL asciiToLongDouble(const char * const numberString, long double
*pldNumber)
{
/* Convert ASCII string to long double data type. */
long double ldReturnValue;
long double ldOneTenth = 0.1e0L;
long double ldTen = 10.0e0L;
long double ldZero = 0.0e0L;
BOOL bFoundDigits = FALSE;
BOOL bIsNegative = FALSE;
const char * pszNum;

/* Check pointers. */
if (pldNumber == NULL) {
return FALSE;
}
if (numberString == NULL) {
*pldNumber = ldZero;
return FALSE;
}

ldReturnValue = ldZero;

pszNum = numberString;

/* Advance past white space. */
while ((*pszNum == ' ') || (*pszNum == '\t'))
pszNum++;

/* Check for sign. */
if (*pszNum == '+')
pszNum++;
else if (*pszNum == '-')
{
bIsNegative = TRUE;
pszNum++;
}

/* Calculate the integer part. */
while ((*pszNum >= '0') && (*pszNum <= '9'))
{
bFoundDigits = TRUE;
ldReturnValue *= ldTen;
ldReturnValue += *pszNum - '0';
pszNum++;
}

/* Calculate the fractional part. */
if (*pszNum == '.')
{
long double ldScale = ldOneTenth;
pszNum++;
while ((*pszNum >= '0') && (*pszNum <= '9'))
{
bFoundDigits = TRUE;
ldReturnValue += ldScale * (*pszNum - '0');
pszNum++;
ldScale *= ldOneTenth;
}
}

/* If this is not a number, return error condition. */
if (!bFoundDigits)
{
*pldNumber = ldZero;
return FALSE;
}

/* If all digits of integer & fractional part are 0, return 0.0 */
if (ldReturnValue == ldZero)
{
*pldNumber = ldZero;
return TRUE; /* Not an error condition, and no need to continue. */
}

/* Process the exponent (if any) */
if ((*pszNum == 'e') || (*pszNum == 'E'))
{
BOOL bIsNegativeExponent = FALSE;
BOOL bGetOut = FALSE;
long lIndex;
long lExponent = 0;
long double ldTooBigTest = LDBL_MAX*ldOneTenth;
long double ldTooSmallTest= LDBL_MIN*ldTen;

pszNum++;
if (*pszNum == '+')
pszNum++;
else if (*pszNum == '-')
{
pszNum++;
bIsNegativeExponent = TRUE;
}

/* What if the exponent is empty? Return the current result. */
if ((*pszNum < '0') || (*pszNum '9'))
{
if (bIsNegative)
ldReturnValue = -ldReturnValue;

*pldNumber = ldReturnValue;

return (TRUE);
}
/* Convert char exponent to number <= 2 billion. */
while ((*pszNum >= '0') && (*pszNum <= '9') && (lExponent <
200000000))
{
lExponent *= 10;
lExponent += *pszNum - '0';
pszNum++;
}

/* Compensate for the exponent. */
if (bIsNegativeExponent)
{
for (lIndex = 1; lIndex <= lExponent && !bGetOut; lIndex++)
if (ldReturnValue < ldTooSmallTest)
{
bGetOut = TRUE;
ldReturnValue = LDBL_MIN;
}
else
ldReturnValue *= ldOneTenth;
}
else
for (lIndex = 1; lIndex <= lExponent && !bGetOut; lIndex++)
{
if (ldReturnValue ldTooBigTest)
{
bGetOut = TRUE;
ldReturnValue = LDBL_MAX;
}
else
ldReturnValue *= ldTen;
}
}

if (bIsNegative)
ldReturnValue = -ldReturnValue;

*pldNumber = ldReturnValue;

return (TRUE);
}
--
Keith Thompson (The_Other_Keith) ks***@mib.org
<http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*>
<http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Aug 9 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.