Determining Precision of a number

I'm tring to determine the precision of a float (ie 123.345 = 3)  The only way I can think of is to convert the float to a string then using strlen.  Are there easier methods?
gmanhartAsked:
Who is Participating?
 
deightonConnect With a Mentor Commented:
#include<math.h>

int decimals(double x)
{
      int c;
      double d = 1,test;
      for(c = 0;1;c++)
      {
            test = x * d;
            if (test == floor(test))
               return c;
            d *= 10;
      }
}

main()
{
      printf("\n%i",decimals(3.141592));
}
0
 
pjknibbsCommented:
Actually, the string method seems a perfectly good way of doing it, and I don't see it's all that difficult--just use sprintf() to convert the number to a string, search for the decimal point using strchr(), then work out the length of the string after that point. I don't think you'll get easier than that.
0
 
ozoCommented:
What's the precision of 123.3450000 ?
or do you want FLT_DIG ?
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
gmanhartAuthor Commented:
Adjusted points from 25 to 50
0
 
gmanhartAuthor Commented:
Excellent solution, especially without even converting the float into a string.  Simple, short and perfect.  Thanks
0
 
ozoCommented:
although it's a strange definition of "precision" that increases with round off error.
0
 
gmanhartAuthor Commented:
Ozo,

Please explain your comment.  Are you talking about problems with the floor function itself?  It would be nice to also consider an option of setting how your precision is to be handled (ie
Precision(Double x, int y) where x would be the number to work on and y would have two options: 0 for 3.12300 = 3 and 1 would be 5 for all decimals after the point)

Now that would allow nice control.  What do you think?
0
 
gmanhartAuthor Commented:
Ozo,

Also, what is FLT_DIG?
0
 
ozoCommented:
FLT_DIG is a macro defined in <float.h> which returns the number of decimal digits such that any floating-point number with FLT_DIG digits can be rounded into a floating-point number with FLT_MANT_DIG radix FLT_RADIX digits without change to the FLT_DIG decimal digits for your implementation.
floor( (FLT_MANT_DIG-1) * log10(FLT_RADIX) ) + 1 if FLT_RADIX is a power of 10, 0 otherwise.
(cf. DBL_DIG)
I'm not sure what you mean by "precision"
Testing when two different round off errors happen to cancel in your floating point processor may or may not be relevent to you.
What would you call the "precision" of an ANSI/IEEE 754-1985 double precision normalized representation of 33141.59? and why?
0
 
gmanhartAuthor Commented:
Ozo,

I'm creating a Histogram program for a Software Engineering course I'm taking.  

I'm need to determine the precision of the numbers the user is entering so that when I bin the numbers I can have +1 decimals more that the user entered to setup the bins.  If the user entered 33141.59, I would consider it a number with 2 decimal places of precision.  A number with trailing zeros to me at this point is not that important since the user as the ablity to override the automatic precision if they don't like the way I trunicate their zeros.  Although I have not test the code completely from deighton, I would only expect it to tell me that 123.123 and 123.12300 have 3 decimal places of precision (even though realisically one has three and the other has 5).  Later I can give the user more options.  Thanks for answering my question and I hope I answered yours

Greg
0
 
ozoCommented:
For binning, wouldn't "precision" only have meaning in the context of all the numbers entered?
Whether deighton's code gives you 3 or 5 or some other result for 123.123 may depend on intricate details of your particular floating point processor in a way that may not make sense to your users.
What kind of processor will the code be running on?
If you are using  ANSI/IEEE 754-1985 floating point, 33141.59 would be stored as 33141.589999999997
Try deighton's code with 2.03, 4.03, 8.03, 8.19, or 32.123
0
 
gmanhartAuthor Commented:
Ozo,

Well now, using deigton's code:

printf("\n%f %i",2.03,decimals(2.03));
printf("\n%f %i",4.03,decimals(4.03));
printf("\n%f %i",8.03,decimals(8.03));
printf("\n%f %i",8.14,decimals(8.14));
printf("\n%f%i",32.123,decimals(32.123));

I got:

2.030000  16
4.030000  2
8.030000  4
8.140000  2
32.123000  4

What is up with that and how can I prevent this from occurring.  I'm using codewarrior on a Macintosh G3 and this is not what I expected.  This will totally mess up my binning!  My routine takes the maximum precision and adds one and then bins based on this.  I find the bin with with the range/# of bins.  Then need to round up to the next precision higher than the data entered.  I need something reliable.

Do you have any ideas on how to prevent this?

Greg
0
 
ozoCommented:
You might see better what's going on if you change your print formats to
printf("\n%.20f",
For the kind og "precision" you want you should probably examine the input from your user stings before converting them into float.
(or perhaps what you really want is an approximation to the least common multiple of the numbers from the user)
0
 
pjknibbsCommented:
gmanhart: It might help if you used double instead of float, although rounding errors may well still occur.
0
 
deightonCommented:
How about reading the value in as a string, counting the digits after the '.' then converting the string to a float.  It could be written to ignore or include trailing zeroes.  

I could provide that code!

EMail me at andrew_deighton@hotmail.com if you need to set me working on that, then I'll put the code here, if I can do it/have enough time.

How are you getting the value into the program?  Are you relying on scanf, or do you have your own user written function?
0
 
deightonCommented:
ozo,

I see the flaw in my reasoning.
0
 
ozoCommented:
pjknibbs, double, or even quad precision, may shift where the errors are noticed, but not eliminate them.
Although rounding errors might be reduced, your sensitivity to rounding errors would be increased.
However, if floats and doubles have different precisions under your implementation, it might work to do the calculations with double and the final test with float.
But that would be sort of a kludge, and non-portable even if it did work, so I would not recommend that approach.
Counting digits in the original string would be a better solution.
0
All Courses

From novice to tech pro — start learning today.