how can modf(), fmod() return 1.0 for the fractional part, why?

B

bsabiston

Hi, I'm trying to get the fractional part of a floating point
number. I've tried fmod() and modf(), and while both do work, they
also occasionally return 1.0 for the fractional part of the number
instead of 0.0. This is on a mac using xcode. This should not ever
happen should it?

Thanks
Bob
 
R

Richard Tobin

Hi, I'm trying to get the fractional part of a floating point
number. I've tried fmod() and modf(), and while both do work, they
also occasionally return 1.0 for the fractional part of the number
instead of 0.0. This is on a mac using xcode. This should not ever
happen should it?

How do you know that they're returning 1.0? Are you printing it out?
Bear in mind that a value like 0.9999999999999 may get printed as 1.0
if you don't use enough digits.

-- Richard
 
B

bsabiston

How do you know that they're returning 1.0?  Are you printing it out?
Bear in mind that a value like 0.9999999999999 may get printed as 1.0
if you don't use enough digits.

-- Richard

hmm. well maybe that is happening. I'm using printf("%f
\n",fmod(val));
 
J

jameskuyper

Hi, I'm trying to get the fractional part of a floating point
number. I've tried fmod() and modf(), and while both do work, they
also occasionally return 1.0 for the fractional part of the number
instead of 0.0. This is on a mac using xcode. This should not ever
happen should it?


My best guess is that you're getting a number that is only slightly
smaller than 1.0, and when you print it out, it gets rounded to 1.0.

Have you checked the return value for equality with 1.0? If you are
just printing it out, are you printing it with enough significant
digits to distinguish nextafter(1.0, 0.0) from 1.0? What do you get if
you use the following printf() statement?

#include <float.h>
#include <stdio.h>

printf("%.*g\n", DBL_DIG+1, fmod(x, 1.0))
 
D

Default User

Hi, I'm trying to get the fractional part of a floating point
number. I've tried fmod() and modf(), and while both do work, they
also occasionally return 1.0 for the fractional part of the number
instead of 0.0. This is on a mac using xcode. This should not ever
happen should it?

Show us your code.




Brian
 
F

Flash Gordon

hmm. well maybe that is happening. I'm using printf("%f
\n",fmod(val));

That does not disagree with what Richard suggested. In fact, since the
default precision for %f is only 6 digits I believe you are guaranteed
to need more digits to be certain the number is 1.0 or greater.
 
M

Martin Ambuhl

Hi, I'm trying to get the fractional part of a floating point
number. I've tried fmod() and modf(), and while both do work, they
also occasionally return 1.0 for the fractional part of the number
instead of 0.0. This is on a mac using xcode. This should not ever
happen should it?

Run the following, modifying EXTRADIGITS as required, and watch the
output. Consider how that might pertain to your question.

#include <math.h>
#include <stdio.h>
#include <float.h>

#define EXTRADIGITS 2

int main()
{
double intpart, fraction, decrement = 1, value;
int i;
printf("Demonstration of modf and default precision\n");
for (i = 0; i <= DBL_DIG + EXTRADIGITS; i++, decrement /= 10.) {
value = 1 - decrement;
printf("decrement = %g (default), %.*g;\n"
" 1-decrement = %g (default), %.*g\n",
decrement, DBL_DIG, decrement, value, DBL_DIG, value);
fraction = modf(value, &intpart);
printf("modf returns:\n"
" fraction = %g (default), %.*g,\n"
" intpart = %g (default), %.*g.\n\n",
fraction, DBL_DIG, fraction, intpart, DBL_DIG, intpart);
}
return 0;
}



Demonstration of modf and default precision
decrement = 1 (default), 1;
1-decrement = 0 (default), 0
modf returns:
fraction = 0 (default), 0,
intpart = 0 (default), 0.

decrement = 0.1 (default), 0.1;
1-decrement = 0.9 (default), 0.9
modf returns:
fraction = 0.9 (default), 0.9,
intpart = 0 (default), 0.

decrement = 0.01 (default), 0.01;
1-decrement = 0.99 (default), 0.99
modf returns:
fraction = 0.99 (default), 0.99,
intpart = 0 (default), 0.

decrement = 0.001 (default), 0.001;
1-decrement = 0.999 (default), 0.999
modf returns:
fraction = 0.999 (default), 0.999,
intpart = 0 (default), 0.

decrement = 0.0001 (default), 0.0001;
1-decrement = 0.9999 (default), 0.9999
modf returns:
fraction = 0.9999 (default), 0.9999,
intpart = 0 (default), 0.

decrement = 1e-05 (default), 1e-05;
1-decrement = 0.99999 (default), 0.99999
modf returns:
fraction = 0.99999 (default), 0.99999,
intpart = 0 (default), 0.

decrement = 1e-06 (default), 1e-06;
1-decrement = 0.999999 (default), 0.999999
modf returns:
fraction = 0.999999 (default), 0.999999,
intpart = 0 (default), 0.

decrement = 1e-07 (default), 1e-07;
1-decrement = 1 (default), 0.9999999
modf returns:
fraction = 1 (default), 0.9999999,
intpart = 0 (default), 0.

decrement = 1e-08 (default), 1e-08;
1-decrement = 1 (default), 0.99999999
modf returns:
fraction = 1 (default), 0.99999999,
intpart = 0 (default), 0.

decrement = 1e-09 (default), 1e-09;
1-decrement = 1 (default), 0.999999999
modf returns:
fraction = 1 (default), 0.999999999,
intpart = 0 (default), 0.

decrement = 1e-10 (default), 1e-10;
1-decrement = 1 (default), 0.9999999999
modf returns:
fraction = 1 (default), 0.9999999999,
intpart = 0 (default), 0.

decrement = 1e-11 (default), 1e-11;
1-decrement = 1 (default), 0.99999999999
modf returns:
fraction = 1 (default), 0.99999999999,
intpart = 0 (default), 0.

decrement = 1e-12 (default), 1e-12;
1-decrement = 1 (default), 0.999999999999
modf returns:
fraction = 1 (default), 0.999999999999,
intpart = 0 (default), 0.

decrement = 1e-13 (default), 1e-13;
1-decrement = 1 (default), 0.9999999999999
modf returns:
fraction = 1 (default), 0.9999999999999,
intpart = 0 (default), 0.

decrement = 1e-14 (default), 1e-14;
1-decrement = 1 (default), 0.99999999999999
modf returns:
fraction = 1 (default), 0.99999999999999,
intpart = 0 (default), 0.

decrement = 1e-15 (default), 1e-15;
1-decrement = 1 (default), 0.999999999999999
modf returns:
fraction = 1 (default), 0.999999999999999,
intpart = 0 (default), 0.

decrement = 1e-16 (default), 1e-16;
1-decrement = 1 (default), 1
modf returns:
fraction = 1 (default), 1,
intpart = 0 (default), 0.

decrement = 1e-17 (default), 1e-17;
1-decrement = 1 (default), 1
modf returns:
fraction = 0 (default), 0,
intpart = 1 (default), 1.
 
K

Keith Thompson

Hi, I'm trying to get the fractional part of a floating point
number. I've tried fmod() and modf(), and while both do work, they
also occasionally return 1.0 for the fractional part of the number
instead of 0.0. This is on a mac using xcode. This should not ever
happen should it?

Recommended reading: Section 14 of the comp.lang.c FAQ,
<http://www.c-faq.com/>.

Additional recommended reading: the rest of it.
 
U

user923005

(e-mail address removed) wrote, On 29/09/08 22:17:


And the best way to find out whether it's 1.0 or greater is to write code:

if ( n >= 1.0 )
    printf( "1.0 or greater\n" );

I never trust debuggers and printf to tell the whole truth when finding
what values variables hold.

In line with C-FAQ 14.5, I would say that sometimes that is the right
thing to do and sometimes it is the wrong thing to do.
It would be especially worrisome if you were looking for mathematical
differences rather than numerical.
Things like:
y = cos(0.0);
y = pow(2.0,28.0);
y = sqrt(34567*34567);
should not be expected to return an integer, even though
mathematically they should.
So if we are wondering "Is cos(0.0) less than 1?" a comparison
operator on the expression is not a reliable way to tell.
 
J

James Kuyper

user923005 said:
In line with C-FAQ 14.5, I would say that sometimes that is the right
thing to do and sometimes it is the wrong thing to do.
It would be especially worrisome if you were looking for mathematical
differences rather than numerical.
Things like:
y = cos(0.0);
y = pow(2.0,28.0);
y = sqrt(34567*34567);
should not be expected to return an integer, even though
mathematically they should.
So if we are wondering "Is cos(0.0) less than 1?" a comparison
operator on the expression is not a reliable way to tell.

There's a key difference here. For real x, cos(x)<=1.0. However, for
real x and y, with y!=0.0, the standard's requirements, as specified in
7.12.10.1p3, mean that

fabs(fmod(x, y)) < y

The difference between <= and < is precisely the difference between
conforming to the standard's specification for fmod() in 7.12.10.1p3,
and not conforming.
 
D

Dik T. Winter

> In line with C-FAQ 14.5, I would say that sometimes that is the right
> thing to do and sometimes it is the wrong thing to do.
> It would be especially worrisome if you were looking for mathematical
> differences rather than numerical.
> Things like:
> y = cos(0.0);
> y = pow(2.0,28.0);
> y = sqrt(34567*34567);
> should not be expected to return an integer, even though
> mathematically they should.
> So if we are wondering "Is cos(0.0) less than 1?" a comparison
> operator on the expression is not a reliable way to tell.

If the question is intended as "is cos(0.0) mathematically less than 1?" you
are right, but in that case a computer program is not able to provide a
reliable answer at all. On the other hand, if the question is "is the value
returned by cos(0.0) less than 1?" a comparison operator is the thing to use.

And even the condition: "fabs(cos(x)) <= 1.0" makes sense. I have seen
programs crash because they assumed it would be true, the implementation by
Cody and Waite is one that can fail here. In Ada the situation is better
because of the stringent requirement for special functions (as I wrote it
in the draft for that: "when a function receives model numbers and the
exact mathematical result is a model number, that number should be returned").
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top