Home > Software engineering >  How to keep decimal accuracy when dividing with floating points
How to keep decimal accuracy when dividing with floating points

Time:07-09

I am working on a project, and I need to divide a very large 64 bit long value. I absolutely do not care about the whole number result, and only care about the decimal value. The problem is that when dividing a large long with a small 64 bit double floating point value, I loose accuracy in the floating point value due to it needing to store the whole numbers.

Essentially what I am trying to do is this:

double x = long_value / double_value % 1;

but without loosing precision the larger the long_value is. Is there a way of writing this expression so that the whole numbers are discarded and floating point accuracy is not lost? Thanks.

EDIT: btw im out here trying to upvote all these helpful answers, but I just made this account for this question and you need 15 reputation to cast a vote

CodePudding user response:

If your language provides an exact fmod implementation you can do something like this:

double rem = fmod(long_value, double_value);
return rem / double_value;

If long_value does not convert exactly to a double value, you could split it into two halves, fmod them individually, add these values together and divide that sum or sum - double_value by double_value.

If long_value or double_value is negative you may also need to consider different cases depending on how your fmod behaves and what result you expect.

CodePudding user response:

long_value is congruent to:

long_value = long_value - double_value * static_cast<long>(long_value / double_value);

Then you can do this:

double fractionalPart = static_cast<double>(long_value / double_value) % 1;

CodePudding user response:

Does the language you're using have a big integer/big rational library? To avoid loss of information, you'll have to "spread out" the information across more memory while you're transforming it so you don't lose the part you're interested in preserving. This is essentially what a big integer library would do for you. You could employ this algorithm (I don't know what language you're using so this is just pseudocode:

// e.g. 1.5 => (3, 2)
let (numerator, denominator) = double_value.ToBigRational().NumAndDenom();

// information-preserving version of long_value / double_value
let quotient = new BigRational(num: long_value * denominator, denom: numerator);

// information-preserving version of % 1
let remainder = quotient.FractionPart();

// some information could be lost here, but we saved it for the last step
return remainder.ToDouble();
  • Related