473,761 Members | 8,813 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

fmod

This code, compiled with visual studio .NET 2003,

double a = 95.022, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);
a = 95.021, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);
a = 95.020, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);

a = 95.022, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));
a = 95.021, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));
a = 95.020, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));

generates this output:

95.022000 - floor(95.022000 / 0.010000) * 0.010000 =
0.0020000000000 0955
95.021000 - floor(95.021000 / 0.010000) * 0.010000 =
0.0010000000000 0477
95.020000 - floor(95.020000 / 0.010000) * 0.010000 =
0.0000000000000 0000
fmod(95.022000, 0.010000) = 0.0020000000000 0359
fmod(95.021000, 0.010000) = 0.0009999999999 9882
fmod(95.020000, 0.010000) = 0.0099999999999 9404

everything makes sense, except for the last line. why does fmod return
0.01 instead of 0.0?

Feb 14 '06 #1
17 6407
jo************@ comcast.net wrote:
fmod(95.022000, 0.010000) = 0.0020000000000 0359
fmod(95.021000, 0.010000) = 0.0009999999999 9882
fmod(95.020000, 0.010000) = 0.0099999999999 9404

everything makes sense, except for the last line. why does fmod return
0.01 instead of 0.0?


I don't know.
I get similar results with my homemade fmod.

/* BEGIN new.c output */

fs_fmod(95.0220 00, 0.010000) is 0.002000
fs_fmod(95.0210 00, 0.010000) is 0.001000
fs_fmod(95.0200 00, 0.010000) is 0.010000

/* END new.c output */

/* BEGIN new.c */

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

double fs_fmod(double x, double y);

int main(void)
{
puts("/* BEGIN new.c output */\n");
printf("fs_fmod (95.022000, 0.010000) is %f\n"
, fs_fmod(95.0220 00, 0.010000));
printf("fs_fmod (95.021000, 0.010000) is %f\n"
, fs_fmod(95.0210 00, 0.010000));
printf("fs_fmod (95.020000, 0.010000) is %f\n"
, fs_fmod(95.0200 00, 0.010000));
puts("\n/* END new.c output */");
return 0;
}

double fs_fmod(double x, double y)
{
double a, b;
const double c = x;

if (0 > c) {
x = -x;
}
if (0 > y) {
y = -y;
}
if (y != 0 && DBL_MAX >= y && DBL_MAX >= x) {
while (x >= y) {
a = x / 2;
b = y;
while (a >= b) {
b *= 2;
}
x -= b;
}
} else {
x = 0;
}
return 0 > c ? -x : x;
}

/* END new.c */

--
pete
Feb 14 '06 #2
jo************@ comcast.net writes:
This code, compiled with visual studio .NET 2003,

double a = 95.022, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);
a = 95.021, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);
a = 95.020, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);

a = 95.022, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));
a = 95.021, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));
a = 95.020, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));

generates this output:

95.022000 - floor(95.022000 / 0.010000) * 0.010000 =
0.0020000000000 0955
95.021000 - floor(95.021000 / 0.010000) * 0.010000 =
0.0010000000000 0477
95.020000 - floor(95.020000 / 0.010000) * 0.010000 =
0.0000000000000 0000
fmod(95.022000, 0.010000) = 0.0020000000000 0359
fmod(95.021000, 0.010000) = 0.0009999999999 9882
fmod(95.020000, 0.010000) = 0.0099999999999 9404

everything makes sense, except for the last line. why does fmod return
0.01 instead of 0.0?


Because none of the literals in your program can be represented
exactly in binary floating-point.

See section 14 of the comp.lang.c FAQ, <http://www.c-faq.com/>.

--
Keith Thompson (The_Other_Keit h) 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.
Feb 14 '06 #3
Thanks Pete.

I take it your code is based on an accepted algorithm for computing
floating-point modulus values. Assuming fmod implementations do the
same thing, or something similar, it seems strange that fmod would
return something that seems that "far off"...if the return value was
0.0000000000045 2 or something like that, fine. but something that
rounds to 0.01...strange.

Here's a defintion of fmod from
http://www.opengroup.org/onlinepubs/.../xsh/fmod.html

The fmod() function returns the value x - i * y for some integer i such
that, if y is non-zero, the result has the same sign as x and magnitude
less than the magnitude of y.

strictly speaking, 0.00999999... is a valid return value since it's
less than 0.01...I haven't cranked through the computation, but maybe
if i went up by one, then the result is less than zero, and it can't
return a negative value for these operands, so somehow you're left with
0.00999999...

calc.exe gets it right <g>

Feb 14 '06 #4

<jo************ @comcast.net> wrote in message
news:11******** *************@z 14g2000cwz.goog legroups.com...
This code, compiled with visual studio .NET 2003,

double a = 95.022, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);
a = 95.021, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);
a = 95.020, b = 0.01;
printf ("%lf - floor(%lf / %lf) * %lf = %.17lf\n", a, a, b, b, a -
floor(a / b) * b);

a = 95.022, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));
a = 95.021, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));
a = 95.020, b = 0.01;
printf ("fmod(%lf, %lf) = %.17lf\n", a, b, fmod(a, b));

generates this output:

95.022000 - floor(95.022000 / 0.010000) * 0.010000 =
0.0020000000000 0955
95.021000 - floor(95.021000 / 0.010000) * 0.010000 =
0.0010000000000 0477
95.020000 - floor(95.020000 / 0.010000) * 0.010000 =
0.0000000000000 0000
fmod(95.022000, 0.010000) = 0.0020000000000 0359
fmod(95.021000, 0.010000) = 0.0009999999999 9882
fmod(95.020000, 0.010000) = 0.0099999999999 9404

everything makes sense, except for the last line. why does fmod return
0.01 instead of 0.0?


First of all, it doesn't return 0.01. According to you, it returns
0.0099999999999 9404 which is "close to" 0.01, but is NOT 0.01.
The roundoff /truncation error encountered is thus 0.0000000000000 0596

Note that the first line is off by a similar amount, the only difference
being that the roundoff/truncation ended up slightly larger than the "exact"
answer rather than slightly smaller.

See comments others have made about the computer's inability to represent
0.01 exactly.

--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project

Feb 14 '06 #5
There's a disconnect. I'm fully aware that 0.00999999... is the closest
the machine can get to representing 0.01 after computing the
floating-point modulo. However, that's not my question...the question
is, why does fmod(95.02, 0.01) return "something that rounds to 0.01"
(quoting myself), whether that's 0.0099999999999 9404 or
0.0100000000000 0596, when the correct decimal modulus of 95.02 and 0.01
is 0.0, and most definitely not 0.01? 95.022 % 0.01 = 0.002. 95.021 %
0.01 = 0.001. 95.020 % 0.01 = 0.000, unless you're using fmod, which
returns something that rounds to 0.01...there's no way that much
difference is due only to limitations on binary floating-point
representation (or implicit type promotions).

In other words, if fmod(95.02, 0.01) returned -0.0000000000000 0404, or
0.0000000000000 0596, I wouldn't have posted.

calc.exe returns 0 for 95.02 mod 0.01, not 0.01. I'd guess that's
because calc.exe uses BCD. It still looks like fmod has an unexpected
boundary condition when x % y ~ 0.

Feb 14 '06 #6
jo************@ comcast.net wrote:
<snip code>
everything makes sense, except for the last line. why does fmod return
0.01 instead of 0.0?


Keeping Keith Thompson's reply in mind, experiment with the
program below. And while you're at it, take a look at the link.
/* a method for computing the single precision
binary representation of a decimal fraction */
/* see:
http://www.nuvisionmiami.com/books/a...oating_tut.htm */

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

int main(int argc, char *argv[])
{
int pow2, mant_bit;
long double minuend, subtrahend, remainder, decfrac;
char mantissa[24];

if(argc != 2 || argv[1][0] != '.')
{
printf("usage: >pgm_name <decimal fraction>\n");
exit(EXIT_FAILU RE);
}
decfrac = 0.0;
minuend = strtold(argv[1], NULL);
printf("\n\tsta rting: %.12Lf\n\n", minuend);

for(pow2=2, mant_bit=0; mant_bit<23; pow2*=2, mant_bit++)
{
printf("%d", mant_bit + 1);
subtrahend = 1.0 / pow2;
if(minuend - subtrahend == 0.0)
{
printf("\tsubtr acting %.12Lf\n", subtrahend);
remainder = minuend - subtrahend;
minuend = remainder;
printf("\tremai nder = %.12Lf\n", remainder);
mantissa[mant_bit] = '1';
decfrac += subtrahend;
continue;
}
else if(minuend - subtrahend > 0.0)
{
printf("\tsubtr acting %.12Lf\n", subtrahend);
remainder = minuend - subtrahend;
minuend = remainder;
printf("\tremai nder = %.12Lf\n", remainder);
mantissa[mant_bit] = '1';
decfrac += subtrahend;
}
else
{
mantissa[mant_bit] = '0';
printf("\n");
}
}
mantissa[mant_bit] = '\0';

printf("\n\tbin ary mantissa: .%s\n", mantissa);
printf("\tdecim al fraction: %.12Lf\n", decfrac);

return 0;
}

Feb 14 '06 #7
jo************@ comcast.net wrote:
There's a disconnect.


A disconnect with what? (See below).

Brian

--
Please quote enough of the previous message for context. To do so from
Google, click "show options" and use the Reply shown in the expanded
header.
Feb 14 '06 #8
On 2006-02-14, jo************@ comcast.net <jo************ @comcast.net> wrote:
There's a disconnect. I'm fully aware that 0.00999999... is the closest
the machine can get to representing 0.01 after computing the
floating-point modulo. However, that's not my question...the question
is, why does fmod(95.02, 0.01) return "something that rounds to 0.01"
(quoting myself), whether that's 0.0099999999999 9404 or
0.0100000000000 0596, when the correct decimal modulus of 95.02 and 0.01
is 0.0, and most definitely not 0.01? 95.022 % 0.01 = 0.002. 95.021 %


printf("%a == %.100f\n", 95.02, 95.02);
printf("%a == %.100f\n", .01, .01);

[cutting off excess zeros in the pasted output]

0x1.7c147ae147a e1p+6 == 95.019999999999 996020960679743 438959121704101 \
5625

0x1.47ae147ae14 7bp-7 == 0.0100000000000 000002081668171 172168513294309 \
377670288085937 5

_those_ are the numbers that fmod sees.
Feb 14 '06 #9
ah...thanks to all for straightening me out, and sorry for the
confusion. And here I thought I was smart...I was just looking at the
output, and didn't account for the fact that the inputs get adjusted
when represented in binary too.

Feb 14 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
4630
by: Zunbeltz Izaola | last post by:
Hi, I have a problem with % operation. It returns a incorrect value in this case: >>> -2.77555756156e-17%1 1.0 where the returned value should be -2.77555756156e-17.
8
5629
by: seia0106 | last post by:
Hello, I have a C++ program , which has following two lines of code z=atan2(x,y); z=(float)(fmod(2*pi+z, 2*pi); The comments written by the other programmer says that second line is used to extend the range of variable z from '-pi to pi' to '-2pi to 2pi'.
2
1807
by: Lonnie Princehouse | last post by:
I've been trying to debug this for two days now, and it's a longshot but I'm hoping that someone here might recognize a solution. I've got a C extension which calls a function in a C library, which calls another function in another library, which calls another function, which calls fmod from the standard C math library. All of these are shared libraries on Linux (x86 Gentoo 2.6.9). In other words, the calling looks like this: Python...
6
8103
by: stau | last post by:
Hi! I'm reading a C book, and it says that fmod() returns the remainder of the exact division of it's arguments. Well, in a exact division, the remainder shall always be 0 (zero), so this don't make any logic (I guess). Anyway, foward in the chapter it says that fmod returns the remainder of the integer division of it's arguments. I checked KnR 2nd ed. and the man page, and still can't figure out wich one is correct.
2
2628
by: Gintautas | last post by:
I'm trying to play a part of wav file. FSOUND_Sample_Load (0,"T01.wav",FSOUND_NORMAL, 0,0); plays all file FSOUND_Sample_Load (0,"T01.wav",FSOUND_NORMAL, 0,90000); plays file until 90000 sample FSOUND_Sample_Load (0,"T01.wav",FSOUND_NORMAL, 25000, 25000); dont't play anything any suggestions?
14
16609
by: Aaron Gray | last post by:
Does anyone have a good fmod() function written in Javascript ? Many thanks in advance, Aaron
7
2582
by: bummerland | last post by:
Hi, I have a problem with the function fmod. Why is fmod(5.7, 0.1) = 0.1 ?? Why is it not 0? tia bummerland
12
4953
by: bsabiston | last post by:
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
0
9554
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9988
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9923
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8813
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6640
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5266
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3911
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3509
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2788
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.