Numerical Algorithm: floor to round to the nearest hundredth

L

lilmax88

I have a program in which I need to take a numeric value for dollars.
There is a "set" function that must screen the value for the following
3 conditions with the indicated handling functionality:

1. Non-negative ==> set to $0.00
2. Out of range (more than 10 digits to represent) ==> set to $0.00
3. More than 2 decimal places ==> truncate to 2.

I have the first two cases down.

I am having trouble with the floor function. If the input is 8.2, the
cost should be interpreted as $8.20, but this is not the case.

Using the algorithm I have right now, the entry condition to process
the number is the following where c is a double representing the cost.

if ( (c*100) != floor(c*100) ) {
c = floor(c*100)/100;
}

Why won't this work? First of all, it enters this block of code for
8.2, which it should not. 820 should equal the floored version of
820, right? wrong. The floored version comes out as 819.

For anything with 3 or more decimal places represented, it functions
as expected. For any number of the form x.y where y is between 0 and
5, exclusive, the block above will run, and the value will be
unchanged. Why??? I also have a cout statement in this block
indicating that the number had too many decimal places, and that it
had been truncated to ___. It says that it was truncated to the
original value, of course.

Am I missing something here? Why do those numbers enter this block?
10.325 is processed to 10.32 as expected, and 8.5 generates no errors
at all, but 3.8 enters the loop and comes out unchanged, as does 8.2.

Anyone?

I have also tried casting down to int and back to double for the
comparison, to truncate the fractional part of the number with the
cast; this does not help.
 
W

weihan

I have a program in which I need to take a numeric value for dollars.
There is a "set" function that must screen the value for the following
3 conditions with the indicated handling functionality:

1. Non-negative ==> set to $0.00
2. Out of range (more than 10 digits to represent) ==> set to $0.00
3. More than 2 decimal places ==> truncate to 2.

I have the first two cases down.

I am having trouble with the floor function. If the input is 8.2, the
cost should be interpreted as $8.20, but this is not the case.

Using the algorithm I have right now, the entry condition to process
the number is the following where c is a double representing the cost.

if ( (c*100) != floor(c*100) ) {
c = floor(c*100)/100;

}

Why won't this work? First of all, it enters this block of code for
8.2, which it should not. 820 should equal the floored version of
820, right? wrong. The floored version comes out as 819.

For anything with 3 or more decimal places represented, it functions
as expected. For any number of the form x.y where y is between 0 and
5, exclusive, the block above will run, and the value will be
unchanged. Why??? I also have a cout statement in this block
indicating that the number had too many decimal places, and that it
had been truncated to ___. It says that it was truncated to the
original value, of course.

Am I missing something here? Why do those numbers enter this block?
10.325 is processed to 10.32 as expected, and 8.5 generates no errors
at all, but 3.8 enters the loop and comes out unchanged, as does 8.2.

Anyone?

I have also tried casting down to int and back to double for the
comparison, to truncate the fractional part of the number with the
cast; this does not help.

You forget considering the effect of the round-off error of the
floating-point numbers.
 
I

Ian Collins

I have a program in which I need to take a numeric value for dollars.
There is a "set" function that must screen the value for the following
3 conditions with the indicated handling functionality:

1. Non-negative ==> set to $0.00
2. Out of range (more than 10 digits to represent) ==> set to $0.00
3. More than 2 decimal places ==> truncate to 2.

I have the first two cases down.

I am having trouble with the floor function. If the input is 8.2, the
cost should be interpreted as $8.20, but this is not the case.
Why not just multiply the values by 100 and assign to an int? Then you
can work in cents.
 
W

weihan

I have a program in which I need to take a numeric value for dollars.
There is a "set" function that must screen the value for the following
3 conditions with the indicated handling functionality:

1. Non-negative ==> set to $0.00
2. Out of range (more than 10 digits to represent) ==> set to $0.00
3. More than 2 decimal places ==> truncate to 2.

I have the first two cases down.

I am having trouble with the floor function. If the input is 8.2, the
cost should be interpreted as $8.20, but this is not the case.

Using the algorithm I have right now, the entry condition to process
the number is the following where c is a double representing the cost.

if ( (c*100) != floor(c*100) ) {
c = floor(c*100)/100;

}

Why won't this work? First of all, it enters this block of code for
8.2, which it should not. 820 should equal the floored version of
820, right? wrong. The floored version comes out as 819.

For anything with 3 or more decimal places represented, it functions
as expected. For any number of the form x.y where y is between 0 and
5, exclusive, the block above will run, and the value will be
unchanged. Why??? I also have a cout statement in this block
indicating that the number had too many decimal places, and that it
had been truncated to ___. It says that it was truncated to the
original value, of course.

Am I missing something here? Why do those numbers enter this block?
10.325 is processed to 10.32 as expected, and 8.5 generates no errors
at all, but 3.8 enters the loop and comes out unchanged, as does 8.2.

Anyone?

I have also tried casting down to int and back to double for the
comparison, to truncate the fractional part of the number with the
cast; this does not help.

To resolve the round-off problem, you may add a tiny amount, e.g.
1.e-10, to your number.
e.g.

Try this :

int main() {

const double TOL = 1.e-10 ;
double a ;

cout << setprecision(2) << fixed ;
for ( a = 0 ; a < 20 ; a += 0.1 ) {
cout << a << "\t"
<< floor((a+TOL)*100)/100. << endl ;
}

return 0 ;
}


If you set the TOL to zero, then you'll see the round-off problem
again.
BTW, The amount of TOL is problem-dependent.
 
L

lilmax88

To resolve the round-off problem, you may add a tiny amount, e.g.
1.e-10, to your number.
e.g.

Try this :

int main() {

const double TOL = 1.e-10 ;
double a ;

cout << setprecision(2) << fixed ;
for ( a = 0 ; a < 20 ; a += 0.1 ) {
cout << a << "\t"
<< floor((a+TOL)*100)/100. << endl ;
}

return 0 ;

}

If you set the TOL to zero, then you'll see the round-off problem
again.
BTW, The amount of TOL is problem-dependent.

thanks to both of you - it turned out that the project compiled and
ran without error, logic or otherwise, a couple days later. I don't
know if it was a temporary thing with the compiler or what, but it
works now. Thanks for the tips - will remember for next time!
 

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,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top