6

Can Anyone help me why x2 prints zero. I guess because of floating point representation X1 is rounded off, is there way to keep the precession.

long double x1, x2;
x1= 0.087912088; // Note: 360/4095 = 0.087912088
x2 = 360/4095;
printf("%Lf, %Lf \n",x1, x2);

Result:

x1 =0.087912
x2= 0.000000
Puppy
  • 144,682
  • 38
  • 256
  • 465
katta
  • 245
  • 1
  • 4
  • 11
  • chris and Levon thanks for the reply. Is there a way to increase the precession. – katta Jun 16 '12 at 02:26
  • To actually store more digits, you'd need an arbitrary-precision library. Just displaying more can be done as Levon says, or with `std::setprecision` in C++. – chris Jun 16 '12 at 02:30
  • @chris I'm working on low level motor control code is C on a QNX embedded system. I will keep that in mind for c++ code. – katta Jun 16 '12 at 02:38
  • To make it less confusing for the others in the future, consider these two dictionary entries: [precession](http://www.tfd.com/precession), [precision](http://www.tfd.com/precision). – Alexey Frunze Jun 16 '12 at 02:39
  • possible duplicate of [something wrong with my float operation](http://stackoverflow.com/questions/10872053/something-wrong-with-my-float-operation) – juanchopanza Jun 16 '12 at 09:18

2 Answers2

10

The problem is integer truncation .. you are dividing two integers => the result will be another integer with the fractional part thrown away. (So for instance in the case when the real result of an integer division would be 3.9, truncation would make it 3 (ie. it doesn't round)).

In your case, if you change this to:

x2 = 360 / 4095.0;  /* one of the operands now has a decimal point */

you'll get

0.087912, 0.087912 

as output.

I.e., as soon as one or both of the operands of the division operator / are float/doubles, the result will be too (i.e., it will be "promoted" to float/double). So I could have changed x2 to

x2 = 360.0 / 4095.0;

or

x2 = 360.0 / 4095;

and would have gotten the same result as above.

As mentioned by @chris just using a . is sufficient too.

Re your question above about precision:

You are already working with long doubles .. I don't think internally you can change anything unless you use some special library, but you can certainly display more digits. E.g.,

  printf("%Lf, %.20Lf \n",x1, x2); 

will yield

  0.087912, 0.08791208791208791895 

Finally, as @edA-qa mort-ora-y reminds us, you can also cast values to certain types, but it matters when you do it. A simple example (note that the values end up as float after the assignment in any case since v is a float):

float v = 0;
                     /* values shown are BEFORE assignment */
v = (5 / 2);         /* value is 2 due to integer truncation before assignment */
v = (float) (5 / 2); /* 2.0 as integer division occurs 1st, then cast to float */
v = (float) 5 / 2;   /* 2.5 since 5 becomes 5.0 through casting first. */
Levon
  • 138,105
  • 33
  • 200
  • 191
3

Built-in operators work on objects of the same type. The result is the same type as the parameters. In this case the division is done on two integers and thus the result is an integer.

x2 = 360/4096;
//   int/int  = int

Thus I would expect a result of 0.

If the operators on a built-in type are different the one will promoted so that they have the same type (and the result is also that type). So what you want is:

x2 = 1.0 * 360/4095;  // or 360.0/4095

// This is
    double * int / int

==> (double * double)/int
==> (double * double)/double
Martin York
  • 257,169
  • 86
  • 333
  • 562