How to determine the number of decimal places in a number? - c

I am writing a program in C.
Is there any way of determining the number of decimal places
in a float number (i.e. 0.123 = 3, 0.123456 = 6 etc.)?
Other than converting the number to a string and using string
functions to pull the characters after the decimal place?
I have a function named computeFare()
float computeFare()
{
totalFare = (3.40 + basicFare) * (1 + surchargePercent);
return totalFare; // **in this case totalFare = 34.567**
}
printf("Total fare is $%.2f\n",
computeFare());
Result : Total fare is $34.56
I did this and it returned 34.56...
I want it to be $34.57
Thanks,
Lawrence.

Not really, the number of decimal places is a function of the internal representation of the number. What you see when you display the number is, is the number as a string for printing.
So if you are interested in the displayed value, you can control the number of decimal places with formatting directives in the first place e.g., %5.2f, or use the string function approach as you mention in your post after the fact once you have the number as a string.
Also, as an aside, would you count trailing zeros?
Perhaps it would be helpful to state your goal for wanting to do this? There might be other ways to accomplish what you are looking to do.
Update:
Based on your update, the problem is really not counting decimal places, rather you are running into represenation issue/rounding errors (not that uncommon). The problem is that some fractional values can't be exactly represented in base 2. Here's an exhaustive explanation: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Take a look at this SO question: Understanding floating point representation errors; what's wrong with my thinking?
You can try this approach to round the value:
float rounded_val = floorf(value * 100.0 + 0.5) / 100.0;
Wikipeadia has a whole article on rounding.

The numbers will (in general) be stored in base 2, so fractional numbers are unlikely to correspond precisely to concise decimal strings. In order to get neat decimals, you're probably going to have to round first.

With printf you can specify the amount of decimal places.
%.0f equals no decimal places
%.4f equals float showing four decimal places

A. I wouldn't think so. even if you could get the mantisa (the exponent value) it would be in base 2.
B. Moreover, floating numbers are not accurate so most likely that if you don't have a perfect round number that you have infinite number of decimal places. you wouldn't see them when you print the number cause there are getting cut.

After your latest edit, it sounds like you just want to round, not that you really care about the number of decimal places in a number.
If this is the case you can use code like this:
#include <math.h>
float computeFare()
{
float totalFare;
totalFare = (3.40 + basicFare) * (1 + surchargePercent);
totalFare = floorf(totalFare * 100 + 0.5) / 100; //round the answer
return totalFare; // **in this case totalFare = 34.567**
}
printf("Total fare is $%.2f\n", computeFare());

Related

How to ensure that floating-point variables entered with 2 decimal places retain their exact value

Is there any way to ensure that a floating-point variable entered by the user, having 2 decimal places after the decimal point, retains its exact value, rather than losing precision?
This is the example case:
I want to round a float with 50 numbers after radix point, like this
Before rounding = 0.70999997854232788085937500000000000000000000000000
to this:
After rounding = 0.71000000000000000000000000000000000000000000000000
I became confused when I wanted to compare a float number in a condition like this:
== Program Start==
Input : 0.71
/* program logic */
if (input == 0.71) {
printf("True !");
} else {
printf("False !");
}
Output : False !
==Program End==
The output was False ! and will always be False ! because the true value of user's input is 0.70999997854232788085937500000000000000000000000000, and not 0.71000000000000000000000000000000000000000000000000
Is there any way to round a float value like that? I read about the potential for inaccuracies with floating point here:
Why Are Floating Point Numbers Inaccurate?
and followed it to these links: Is there a function to round a float in C or do I need to write my own?
and Rounding Number to 2 Decimal Places in C
However, these don't answer my question. If I use ceilf(input * 100) / 100 function, it will make the input 0.71 into 0.71000 when printf()d using %.5f format - which seems to work. But when I print with %.50f, the real input value appears as 0.709999978542327880859375. So, I can't compare to that value in my condition.
So, if floating point can never be accurate, what is the trick for the program logic above to get a true return value at that condition?
All of the user's input comes in as text. The easiest -- and, possibly, safest -- way to check it is to compare it as a string before even converting to number:
if (strcmp("0.71", input) == 0) {
printf("True !");
} else {
printf("False !");
}
Of course, this may not be acceptable to you, if you wish to check for something other than equality :)
The other point is that you are interested in fixed, rather than floating numbers here -- but are confusing them with actual integers. If hundredths is what you'd like to work with, then work with the integer numbers of hundredths... For example, consider money -- instead of using float (or double) to store the amounts of dollars (like $7.61), use int (or, god bless you, long) to store cents (like ยข761).
Similarly, for another example, if you are counting time and need precision of one thousandth of a second, then use integer numbers of milliseconds, instead of floating-point number of seconds.
This will sidestep your entire problem altogether and may also make your programs faster...
I'm sure this question has been answered before, however:
float rounded_down = floorf(input * 100) / 100; /* Result: 0.70 */
float nearest = roundf(input * 100) / 100; /* Result: 0.71 */
float rounded_up = ceilf(input * 100) / 100; /* Result: 0.71 */
The library this functions belongs I think is math.h.
You can test equality with a range as you've experienced.
Just rewrite your equality test with:
if(input <= .71 + EPSILON && input >= .71 - EPSILON) {
}
Here you can create your own EPSILON based on your tolerance, or you can perhaps use FLT_EPSILON from #include<cfloat> for C++ or #include <float.h> in C.
Recall that floats do not have 50 digits of decimal precision. So trying to round at the 50th decimal place isn't going to work out so well. Floats have about 6 (sometimes more) digits of precision.

How do I check accuracy on specified decimal places in C

I need to specify that I need two numbers be the same upon 3rd decimal place: 1.2345 and 1.2348 is correct. But 1.2345 and 1.2388 is not correct. And I need let user specify how many places should program check.
I was thinking about something like that:
do {
x = f(i++);// will count some number with i iterations
x_next = f(i++);// will count some number with i+1 iterations
} while (fabs(x - x_next) > accuracy);// there should be some difference, cause more iterations = accurate number, but different numbers = different iterations needed
But I don't know how should I convert number 3 to 0.001.
Can you suggest me something please?
Divide 1.0 by 10 3 times to get 0.001.
To convert 3 to .001 use the pow() function. .001 = pow(10, -3) (It returns base to the power of exponent, in this case 10^-3.) You would need to include the math.h library to use pow().
A word of caution. abs(x-y)<.001 does not guarantee that they agree on 3 decimal places. For example, 1.00000 and .99999 don't agree on any decimal places but abs(1.00000-.99999)=.00001 < .001.
If you need to check if two numbers are the same upon 3rd decimal place, you can simply multiply both values with 1000 and compare them as integers.
You get the picture, you have to mutiply with 10^decimal_place.
EDIT:
If rounding is required, then simply add 5/10^(decimal_place+1) before multiplying.
Well, there is two ways to approach this:
If you want to see if the difference of two numbers is less than 10 to the power of minus your number (in your example 0.001), you can use the solutions provided. However, it says 1.3458 is equal to 1.3462, which doesn't seems what you wanted.
You can convert the numbers to integers before. In your example (3 decimal places), you can multiply your number by 1000 (10 to the power of 3), and get it's integer part (with an (int) cast), as in:
int multiplier = pow(10,decimalPlaces);
int number1 = (int) numberOriginal1*multiplier;
int number2 = (int) numberOriginal2*multiplier;
if(number1 == number2)
printf("Success\n");
else printf("Fail\n");
Hope that helps.
If you just want to give it as an output simply use printf("%.3f",number)
or if you want to it other way, just go through this question,
Rounding Number to 2 Decimal Places in C

How do you read an input value to a desired amount of digits after the decimal point?

What I am saying is that lets say the user inputs a floating point number for ex 4.624.
Then you you have to read this value using scanf and then you might use it to do some sort of calculation by plugging it in a formula or something similar. How can you read that number to two digits after the decimal point which in this case would be 4.62 so that's the number you use in the formula and not the whole number of 4.624.
float x = 4.624;
float x_truncated_to_two_decimal_places = floor(x*100.0) / 100.0;
or
float x_rounded_to_two_decimal_places = round(x*100.0) / 100.0;
depending on what you want.

How to round display of float such that last two digits are always "00"?

I need to write a program in C that does the following:
Write a program so that when the user enters a floating point number, it rounds off the number to 3 decimal places. When displaying the result, display 5 decimal places, and this means the 4th and 5th decimal place number will both be 0.
How do I round it to 3 decimal places and then display two zeroes? I am not allowed to use any sort of math library functions.
printf("%.5f\n",(int)(number*1000+0.5)/1000.0);
Well, "no math" method :D
printf("%.3f00\n", n);
(Usually subject to Round-to-Nearest-Even; see R..'s comment.)
There are two steps to your task:
1) Round the number to three (3) decimal places.
double n = 0.123456;
n = ((int) (n * 1000.0)) / 1000.0; // => 0.123
2) Display the number to five (5) decimal places.
printf("%.5f\n", n); // => 0.12300

Why do I get different results only 1% of the time?

I am trying to truncate everything past the hundredths decimal. (13.4396 would be 13.43) Sholdn't it always or never work?
I have this formula that works 99%:
input = (( (double) ((int)(orgInput * 100)) ) / 100) ;
Then I have this formula sequence that is arithmetically equivalent:
input = (orgInput * 100);
input = (int) input;
input = (double) (input);
input = input / 100;
These inputs do not give the desired result (Formula truncates and round down, while the broken down steps output the desired result):
12.33
99.99
22.22
44.32
56.78
11.11
And then an even bigger mystery to me is why 33.30 does not work on either of them. Below is my program that runs continuously to demonstrate my problem.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double orgInput, input;
while (4!=3)
{
printf("Please enter the dollar amount (up to $100) => ");
scanf("%lf", &orgInput);
/* Truncates anything past hundredths place */
input = (orgInput * 100) ;
printf("\n1. input is %g \n ", input);
input = (int) input ;
printf("\n2. input is %g \n ", input);
input = (double) (input) ;
printf("\n3. input is %g \n", input);
input = input / 100 ;
printf("\n4. input is %.2lf \n", input);
input = (( (double) ((int)(orgInput * 100)) ) / 100) ;
printf("\nUsing the formula the input is %.2lf \n \n\n", input);
}
system("PAUSE");
return 0;
}
Thank you in advance!!!! P.S. Sorry for the formatting I am still getting used to stackoverflow
Key phrases:
Double to int conversion
Precision error
I think you are suffering from floating-point precision errors.
You should be able to fix this by doing:
const double epsilon = 1e-10; // Or some suitable small number
input = floor(orgInput * 100 + epsilon) / 100;
An alternative is to stop this from happening on input. Instead of reading in a double, you read a string and then parse that to get out the dollar and cents amount (cents being exactly 2 digits following the decimal point, if any). You can then ignore everything else.
In general, if you are working with money truncated to cents, you might be best to keep it in cents and use integers. Either that or round instead of truncate (for my above example, that would mean an epsilon of 0.5).
You need to understand that floats are represented in binary as:
2^(exponent) * mantissa
Exponent is a standard integer, but mantissa (a value between 1 and 2) is a number of bits where each bit represents a fraction: 1, 1/2, 1/4, 1/8, 1/16 and so on... Therefore it is not possible for the mantissa to represent certain values exactly, it will have an accuracy of +/- some fraction.
For example you mentioned 33.30. As a float 33.30 can only be: 2^5 * mantissa.
In this case the mantissa has to be 33.30/32 = 1.40625 exactly. But by making it out of the fractions the closest it can be is be is: 1.0406249999999999111821580299874767661094. So the actual value of the double is not 33.30, its 33.2999999999999971578290569595992565155029296875, which of course rounds DOWN to 33.29 when you do the type cast to integer.
The correct way to fix your program is not to scan in a float in the first place. You should be scanning in two integers seperated by decimal, and if scanf returns a value that indicates it did not scan two integers, then scan it as one integer for the case of a dollar only value.
Sadly, printf works by conversions to ints inside it and will not properly print any double precision floats that have more than 6 decimal places, which is why you see it as 33.30 even through you are asking printf to print the value of a double.
Most machines use binary, not decimal floating point. While binary-to-decimal conversion always gives exact values (in theory), it's impossible to convert from decimal to binary without rounding (I'm not considering the impractical case when numbers can have infinite number of digits).
As such, all your binary floating-point numbers are going to be slightly off of what they would've been in decimal.
The only 1-digit decimal fractions that can be represented in binary are: .0, .5.
Likewise, 2-digit decimal fractions exactly representable in binary are: .00, .25, .50, .75 (see here).
If you want, which I doubt, you can round to the nearest fraction of the four.

Resources