# Rounding and Truncating problem in C

Discussion in 'C' started by moogle1979, Feb 2, 2010.

1. ### moogle1979New Member

Joined:
Feb 2, 2010
Messages:
8
0
Trophy Points:
0
I tested it using the purchase price if 23.455, when doing it Iuse 0.005 to help with the rounding issue however it is not rounding right when I truncate it

For example

The Delmar store has a tax rate of 7.25% which should show a tax of 1.7004875. Rounding that it would be 1.70, even to account for the rounding in C with 0.005 it should still truncate to 1.70 however it is showing 1.71. What am I doing wrong?

Here is the program I have at the moment

Code:
```#include <stdio.h>
#include <windows.h>

int main (void) //Main program function
{

char    *stores[3] = {"Del Mar", "Encinitas", "La Jolla"};
float    taxPercent[3]={7.25, 7.5, 7.75}; // Tax variable for all three stores
float    price; //float variable for the price

do {
printf("\t\tKudler Fine Foods Tax Calculator\n\n");  // prints header
printf("Please enter the amount of your purchase: ");
scanf("%f", &price);
if (0.0 > price) {
printf("\n\nPurchase amount must be positive");
sleep(2000);
system("cls");
}
} while(price < 0.0);

float newPrice = price + 0.005;

float taxTotal[3] = {price * (taxPercent[0]/100), price * (taxPercent[1]/100), price * (taxPercent[2]/100)}; //calculates the total for each store
float totalPrice[3] = {price + taxTotal[0], price + taxTotal[1], price + taxTotal[2]};
printf("\n\n\t%s store\n", stores[0]); //prints tax information for Del Mar
printf("\n\tPurchase price: %.2f", newPrice);
printf("\n\tSales tax: %.2f", taxTotal[0] + 0.005);
printf("\n\tTotal Purchase Price: %.2f", totalPrice[0] + 0.005);

printf("\n\n\t%s store\n", stores[1]); //prints tax information for Del Mar
printf("\n\tPurchase price: %.2f", newPrice);
printf("\n\tSales tax: %.2f", taxTotal[1] + 0.005);
printf("\n\tTotal Price: %.2f", totalPrice[1] + 0.005);

printf("\n\n\t%s store\n", stores[2]); //prints tax information for Del Mar
printf("\n\tPurchase price: %.2f", newPrice);
printf("\n\tSales tax: %.2f", taxTotal[2] + 0.005);
printf("\n\tTotal Purchase Price: %.2f", totalPrice[2] + 0.005);

getch(); // waits for user to press a key

return 0; // return of int main()

} // end main
```

2. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,012
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
Computers can't store floating point numbers precisely; they convert them to binary and there are some losses. You know about these losses in decimal, for example what's 3/10 as a number? 0.3333... you cannot represent it in a finite number of digits.

So it is with computers. When you try to store 1.70, the computer converts it into binary which only approximates the true value. So the maths on floating point numbers doesn't work properly. 1.70+0.01 != 1.71.

There are two ways of getting round this. The most accurate way is to switch to integers, and instead of storing 1.70, store 170 with a note somewhere that this is the true value multiplied by 100. Then the maths will be exact.

Or when comparing, you can subtract, take the absolute value and compare the difference with a suitably small number. So if you're comparing 1.70+0.01 with 1.71, what you might do is subtract 1.70 from 1.71 and see if the difference is less than, say, 0.00005.

3. ### moogle1979New Member

Joined:
Feb 2, 2010
Messages:
8
0
Trophy Points:
0
Some one mentioned doing it basically this way

Code:
```int sale = ((taxPercent[0]/100) * price)  * 100;
int decimal = sale % 100;
int wholeSale = sale/100

printf("Purchase Price: %d.%d", wholeSale, decimal);
```
Since I have three stores is there a way to do this in arrays?
When I do this is comes out right with the first store. The second store however, with the number I use (23.455) of a tax rate of 7.5 shows a tax of 1.759125; shows in on there as 1.75 when it should show 1.76. Did I do it right and it should show the 1.75 or is there a way to do it to get it to be 1.76?

I hope this all makes sense and thanks in advance for any help you can provide.

4. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,012
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
Looks like you need to round off. 1.759xxx -> 1.76. You can round to a whole number by adding half then casting to an int (so 1.4->1.9->1, 1.7->2.3->2, so this rounds to the nearest integer), so to round to the nearest 1/100th you can do something similar.

5. ### moogle1979New Member

Joined:
Feb 2, 2010
Messages:
8
0
Trophy Points:
0
Well it is allot of coding but I think I have done it. Tell me what you think

Code:
```/********************************************************************
*   Tax Calculator for CSS 561                                      *
*   Author: Gregory Hegykozi                                        *
*   Due Date: February 7, 2010                                      *
*   Facilitator: Michael Flanagan                                   *
*********************************************************************
*        Libraries Included                                         *
*             math.h                                                *
*             stdio.h                                               *
*             windows.h                                             *
*********************************************************************
*          Variables used                                           *
*stores: an array storing the names of the stores                   *
*taxPercent: used as an array to store the tax price for each store *
*price: float variable for price                                    *
*taxTotal: used as an array to calculate tax totals                 *
*totalPrice: float variable to determine total purchase             *
*********************************************************************
*                 Company                                           *
*               Kudler Fine Foods                                   *
*********************************************************************
*            Stores Included                                        *
*               Delmar                                              *
*               Encinitas                                           *
*               La Jolla                                            *
*********************************************************************
*                     Main Version                                  *
* Version: Create a tax calcutator that gives prices for            *
* the 3 Kudler Fine Foods Store showing the tax for 125.00 dollars  *
*********************************************************************
* First Addition: Add in the ability for the user to choose their   *
* own purchase price while checking that the user does not put      *
* in a negative number while showing
********************************************************************/

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

int main (void) //Main program function
{

char    *stores[3] = {"Del Mar", "Encinitas", "La Jolla"}; //store variables
float	taxPercent[3]={7.25, 7.5, 7.75}; // Tax variable for all three stores
float	price; //float variable for the price

do {  // starts a do while loop
printf("\t\tKudler Fine Foods Tax Calculator\n\n");  // prints header
printf("Please enter the amount of your purchase: "); //asks for purchase amount
scanf("%f", &price);  // scans user input

// verifies user input was positive
if (0.0 > price) {
printf("\n\nPurchase amount must be positive");
sleep(2000);
system("cls");
}
} while(price < 0.0);

// creates usable variables for price, tax, and total purchase
short saleTax[3] = {(((taxPercent[0]/100) * price) + 0.005) * 100, (((taxPercent[1]/100) * price) + 0.005) * 100, (((taxPercent[2]/100) * price) + 0.005) * 100};
short decimal[3] = {saleTax[0] % 100, saleTax[1] % 100, saleTax[2] % 100};
short wholeTax[3] = {saleTax[0]/100, saleTax[1]/100, saleTax[2]/100};
float roundPrice = {price + 0.005};
float taxTotal[3] = {floor((price*(taxPercent[0]/100))*1000)/1000, floor((price*(taxPercent[1]/100))*1000)/1000, floor((price*(taxPercent[2]/100))*1000)/1000};
float totalPrice[3] = {roundPrice + taxTotal[0],roundPrice + taxTotal[1],roundPrice + taxTotal[2]};

//prints purchase information for Del Mar
printf("\n\n\t%s store\n", stores[0]);
printf("\n\tPurchase price: %.2f", roundPrice);
printf("\n\tSales tax: %d.%d", wholeTax[0], decimal[0]);
printf("\n\tTotal Purchase Price: %.2f", totalPrice[0]);
//end purchase information for Del Mar

//prints purchase information for Encinitas
printf("\n\n\t%s store\n", stores[1]);
printf("\n\tPurchase price: %.2f", roundPrice);
printf("\n\tSales tax: %d.%d", wholeTax[1], decimal[1]);
printf("\n\tTotal Price: %.2f", totalPrice[1]);
//end purchase information for Encinitas

//prints purchase information for La Jolla
printf("\n\n\t%s store\n", stores[2]);
printf("\n\tPurchase price: %.2f", roundPrice);
printf("\n\tSales tax: %d.%d", wholeTax[2], decimal[2]);
printf("\n\tTotal Purchase Price: %.2f", totalPrice[2]);
//end purchase information for La Jolla

getch(); // waits for user to press a key

return 0; // return of int main()

} // end main
```

6. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,012
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
"allot" isn't a word, or if it is, it doesn't mean "a lot". Let's see what happens if we use the "a xyyy"="axxyyy" principle some more...

Your code isn't formatted well. This makes it difficult to follow - a reviewer would need to reformat it to be able to make any sense of it. This isn't "allot" of code, by the way, it's only "affew" lines. The lack of good formatting will make this program "allot" harder than it needs to be. Here are the first few lines formatted correctly:

Code:
```int main (void) //Main program function
{
char    *stores[3] = {"Del Mar", "Encinitas", "La Jolla"}; //store variables
float	taxPercent[3]={7.25, 7.5, 7.75}; // Tax variable for all three stores
float	price; //float variable for the price

do {  // starts a do while loop
printf("\t\tKudler Fine Foods Tax Calculator\n\n");  // prints header
printf("Please enter the amount of your purchase: "); //asks for purchase amount
scanf("%f", &price);  // scans user input

// verifies user input was positive
if (0.0 > price)
{
printf("\n\nPurchase amount must be positive");
sleep(2000);
system("cls");
}
} while(price < 0.0);

... and you can do the rest.

```
Comments are there to explain what the code is doing and relate it to the higher level design so that it can be understood what the code is for. They are NOT for stating the obvious. This comment is "awwaste" of space because it doesn't do anything more than state the obvious: "do{" always starts "addo" loop because that's the syntax of a do loop!
Code:
```	do {  // starts a do while loop
```
Code:
```int main (void) //Main program function.  Well duh.  Obviously it's the main function.

char    *stores[3] = {"Del Mar", "Encinitas", "La Jolla"}; //store variables
Well duh.  Obviously you're storing variables.  What is the significance of them?

float	taxPercent[3]={7.25, 7.5, 7.75}; // Tax variable for all three stores
See, you can do comments correctly!

printf("\t\tKudler Fine Foods Tax Calculator\n\n");  // prints header
printf("Please enter the amount of your purchase: "); //asks for purchase amount
scanf("%f", &price);  // scans user input
All pointless comments.  It's just as obvious what the code is doing without them.

// verifies user input was positive
if (0.0 > price)
Well duh.  Obviously this is checking if price is negative.

} while(price < 0.0);
Why isn't there a "// ends a do while loop" comment here?  (NOOO, I'm not implying there should be one!)
```
Don't write your if statements the wrong way round. If you're checking if price is less than zero, check that price is less than zero, not if zero is bigger than price.
Code:
```if (0.0 > price)

But if you're going to insist on doing it, then be consistent:
} while(price < 0.0);
```
Watch out for duplicate code; this is "aggreat" way to introduce bugs - if you need to change it, then you need to remember to change it everywhere, and you get "abbug" that can be difficult to track down when you don't (because you think you've fixed that issue, so you waste time looking everywhere else).

Code review stops there because that's as far as I reformatted the code, except for one final point. Try to write self-documenting code, then that way the need for comments is reduced. For example
Code:
```return 0; // return of int main()
```
Most compilers will define EXIT_SUCCESS as zero; use that instead:
Code:
```    return EXIT_SUCCESS;
```
Very clear and no need for any kind of comment there.

7. ### moogle1979New Member

Joined:
Feb 2, 2010
Messages:
8
0
Trophy Points:
0
These are stuff are teacher is telling us not to do. For instance our teacher is telling us to always use:

Code:
```return 0;
```
and our teacher told us to make it well documented with as few comments as possible and not to document every line.
as far as the following
Code:
```if (0.0 > price)

But if you're going to insist on doing it, then be consistent:
} while(price < 0.0);
```
I asked the teacher if the following would work

Code:
```
if (price > 0.0)

} while (price < 0.0)
```
as I always like to put the variable first in arguments, however the teacher sent me a message back say it should be the way it is now as it looks better.

I appreciate your comments and sorry about the allot instead of a lot. I am not the best at grammar.

8. ### moogle1979New Member

Joined:
Feb 2, 2010
Messages:
8
0
Trophy Points:
0
I just talked to the teacher and when confronted he said, he never mentioned it because everyone is assumed to have windows which automatically returns 0

This has happened before the teacher posted the following program used from an example

Code:
```#include <stdio.h>
#include <time.h>
#include <system.h>

/********************************************
FUNCTION PROTOTYPES
********************************************/
int sportsQuestion(void);
int geographyQuestion(void);
void pause(int);
/*******************************************/
/********************************************
GLOBAL VARIABLE
********************************************/
int giResponse = 0;
/*******************************************/
main()
{
do {
clrscr();
printf("\n\tTHE TRIVIA GAME\n\n");
printf("1\tSports\n");
printf("2\tGeography\n");
printf("3\tQuit\n");
printf("\n\nEnter your selection: ");
scanf("%d", &giResponse);
switch(giResponse) {
case 1:
if (sportsQuestion() == 4)
printf("\nCorrect!\n");
else
printf("\nIncorrect\n");
pause(2);
break;
case 2:
if (geographyQuestion() == 2)
printf("\nCorrect!\n");
else
printf("\nIncorrect\n");
pause(2);
break;
} //end switch
} while ( giResponse != 3 );
} //end main function
/**********************************************************
FUNCTION DEFINITION
**********************************************************/
int sportsQuestion(void)
{
int iAnswer = 0;
clrscr();
printf("\tSports Question\n");
printf("\nWhat University did NFL star Deon Sanders attend? ");
printf("\n\n1\tUniversity of Miami\n");
printf("2\tCalifornia State University\n");
printf("3\tIndiana University\n");
printf("4\tFlorida State University\n");
printf("\nEnter your selection: ");
} //end sportsQuestion function
/**********************************************************
FUNCTION DEFINITION
**********************************************************/
int geographyQuestion(void)
{
int iAnswer = 0;
clrscr();
printf("\tGeography Question\n");
printf("\nWhat is the state capital of Florida? ");
printf("\n\n1\tPensacola\n");
printf("2\tTallahassee\n");
printf("3\tJacksonville\n");
printf("4\tMiami\n");
printf("\nEnter your selection: ");
} //end geographyQuestion function
/***********************************************************
FUNCTION DEFINITION
************************************************************/
void pause(int inNum)
{
int iCurrentTime = 0;
int iElapsedTime = 0;
iCurrentTime = time(NULL);
do {
iElapsedTime = time(NULL);
} while ( (iElapsedTime - iCurrentTime) < inNum );
} // end pause function
```
The problem with this is the compiler they recommend accept non-ANSI functions like clrscr, however since Miracle C does not run on my Operating System I had to use Dev C++ "which I am glad I did" because I found out clrscr does not run on Dev C++ because it is a Borland Expression from conio.h which is not standard ANSI. I posed this to him and he had no solution except to force the compiler to use it with voids. I looked it up and found out the standard ANSI for something like that is

Code:
```system("cls");
```
I do so much research because I do not put much stock in what the teacher says. Some they say is good but they like teaching non-portable ways and do not even mention portable options.