fmod/floor problem (double varliable returning 1 when computing fractional remainder)

I'm working on a function to compute the number of decimal places in a variable. It works fine some of the time, but other times it behaves unpredictably. I read that this is due to a double representation error but I don't fully understand what the person was telling me.

Here is the simple function:

1
2
3
4
5
6
7
8
9
10
int f_Decimals(double num) {

	int i = 0;
	while (fmod(num, floor(num))) {
		cout << i << ": " << fmod(num, floor(num)) << "\n";
		i++;
		num = num * 10;
	}
	return i;
}


For example, if I pass the number 1.233256 to the function, fmod(num, floor(num)) becomes the following values in sequence:

.233256
.33256
.3256
.256
.56
.6
1
1
1
1
.999998
.999985
.999756
.998047
.984375
.75

Other numbers work fine. Clearly the fmod function is returning a value close to 1 when it tried to fmod(6.0, 6.0). Any help as to how to fix this problem and have the function compute the proper number of decimal places would be appreciated.

The point is, I'm trying to make a function that rounds a double value to an arbitrary level of decimal precision. I assume I'm having trouble because of base-8 and base-10 differences. Is there something that can help me achieve my desired effect? Here's the round function I'm working on... bear in mind I've been programming for a week, so it's probably not pretty.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
double f_Round(double num, int place) {

	int dec = f_Decimals(num);
	double val;


	if (dec > place) {
		
		
		double numtemp = num;
		numtemp = numtemp * pow(10, place);
		double numtemp2 = fmod(numtemp, floor(numtemp));
		numtemp = numtemp * pow(10, 0-(place));
		double testdigit = numtemp2 * 10;
		testdigit = floor(testdigit);
		int option;
		cout<< testdigit << "/n";
		if (testdigit >= 5) {
			if (testdigit == 5) {
				double temp = numtemp2;
				temp = fmod(temp, floor(temp));
				temp = temp * 10;
				temp = floor(temp);
				if (temp < 5) {option = 0;}
				else {option = 1;}
			}
			else {option = 1;}
		}
			
		else {option = 0;}
		cout <<"Option:" << option << "\n";
		if (option == 1) {
			double temporary = num;
			temporary = temporary * pow(10, place);
			temporary = temporary + 1;
			double remain = fmod(temporary, floor(temporary));
			remain = remain * pow(10, 0 - (place));
			temporary = temporary * pow(10, 0 - place);
			val = temporary - remain;}
		else if (option == 0) {
			double temporary = num;
			temporary = temporary * pow(10, place);
			double remain = fmod(temporary, floor(temporary));
			remain = remain * pow(10, 0 - (place));
			temporary = temporary * pow(10, 0 - place);
			val = temporary - remain; }
		else {val = num;}

	}

	if (dec > place) {return val;}
	else {return num;}
}
Last edited on
Rounding to an arbitrary precision and displaying the digits correctly are entirely different problems.

Due to base 2 <-> base 10 conversion problems, it's very unlikely that the stored value will be exactly the one you wanted. But that's generally not a problem because the error will be very small.
In your example, the error was of the order of 10-10. Is that really a problem ?
Topic archived. No new replies allowed.