1

I am getting wrong value while converting float to unsigned integer

TMAC_PAYLOAD_SCALE = 0.10
Data = (unsigned short)(mData / TMAC_PAYLOAD_SCALE);
189.20/0.10 = 1891  (I am expecting 1892)
184.59/0.10 = 1845  (I am expecting 1846)

Tried with both round and ceil function but still getting wrong answer

Sijith
  • 3,740
  • 17
  • 61
  • 101
  • `round` should give the correct result - are you sure you used it correctly ? – Paul R Sep 02 '14 at 11:01
  • [Looks fine to me](http://coliru.stacked-crooked.com/a/73b541ddbfdab551) (I used round for the first, but you need it for the second too). The need for round in the first case is only due to the joys of floating-point computations : 10.0*189.20 gives you the right answer. In the second case, it is due to the fact that a cast truncates the data in some way, so 1845.9 becomes 1845. – Nelfeal Sep 02 '14 at 11:09
  • @PaulR In case of VC yes. But generally speaking, the type `double` (returned by `round`) is not guaranteed to be IEEE 754 and to allow _exact_ representation for all integers. So we may have cases when after truncating the result is less than expected. (I tried to illustrate it with `float` in my answer.) – AlexD Sep 06 '14 at 22:30

2 Answers2

3

If C++ compiler uses IEEE 754 you can try round function:

Data = (unsigned short)round(mData / TMAC_PAYLOAD_SCALE);

However, assuming that the result of division is non-negative, the following approach is perhaps better:

Data = (unsigned short)(mData / TMAC_PAYLOAD_SCALE + 0.5);

The reason is that for floating-integral conversion the fractional part is just discarded. So if the rounding function cannot represent the exact integral value N, and returns a value "slightly less" than N, then after casting we get N-1.

This problem can be illustrated by the following (IEEE 754 compatible) code:

int a = 16777217;
float f = a; // not double
int b = f;
cout << a << " " << b << endl;

which outputs

16777217 16777216

While the described problem should not happen in case of IEEE 754 and round function (since round returns double which allows exact representation for integers), still the first approach does not look very convenient because we have to keep all these assumptions in mind.

Community
  • 1
  • 1
AlexD
  • 32,156
  • 3
  • 71
  • 65
0

what i have tried-

#include <stdio.h>
#include<math.h>
int main ()
{

        printf("%hd\n",(unsigned short)ceil(189.20/0.10)); // you can use ceilf also
        printf("%hd\n",(unsigned short)floor(184.59/0.10));

        return 0;
}

output-

root@sathish1:~/My Docs/Programs# ./a.out 
1892
1845
Sathish
  • 3,740
  • 1
  • 17
  • 28