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();