1

I have the following code:

typedef __int64 BIG_INT;
typedef double CUT_TYPE;

#define CUT_IT(amount, percent) (amount * percent)

void main()
{
    CUT_TYPE cut_percent = 1;

    BIG_INT bintOriginal = 0x1FFFFFFFFFFFFFF;
    BIG_INT bintAfter = CUT_IT(bintOriginal, cut_percent);
}

bintAfter's value after the calculation is 144115188075855872 instead of 144115188075855871 (see the "2" in the end, instead of "1"??).

On smaller values such as 0xFFFFFFFFFFFFF I get the correct result.
How do I get it to work, on 32bit app? What do I have to take in account?
My aim is to cut a certain percentage of a very big number.

I use VC++ 2008, Vista.

easwee
  • 15,757
  • 24
  • 60
  • 83
Poni
  • 11,061
  • 25
  • 80
  • 121
  • Is the "cut_percent" always going to be n/100 for some integer n, or can "cut_percent" be an arbitrary double? – Peter Milley Jul 26 '10 at 23:52
  • @Peter: arbitrary double that is. The code example uses 100% just to emphasize the fact that the value is wrong no matter how you look at it. – Poni Jul 27 '10 at 00:37

2 Answers2

5

double has a 52 bit mantissa, you're losing precision when you try to load a 60+ bit value into it.

bstpierre
  • 30,042
  • 15
  • 70
  • 103
  • I usually use 'long double' on g++, which gives greater precision. Having just checked though, it appears that VC++ doesn't really respect this. http://en.wikipedia.org/wiki/Long_double – Aaron McDaid Jul 27 '10 at 02:06
3

Floating point calculations aren't guaranteed to be perfectly accurate, and you've defined CUT_TYPE as double.

See this answer for more info: Dealing with accuracy problems in floating-point numbers

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I know I should "accept" a certain range, although hoping for someone to come up with a way around this. – Poni Jul 26 '10 at 23:41
  • 2
    The way around it is to use a bignumber library that supports arbitrary precision, and rational numbers. – Ben Voigt Jul 26 '10 at 23:54