5

How can I find if one floating point number is a multiple of another?

e.g. Is 500.4 a multiple of 0.001?

double v = 500.4;
double multipleOf = 0.001;

double remainder = v % multipleOf;
// 0.000999999999966846

For performance I'd prefer not converting the doubles to decimals. How can I test this given the imprecise nature of floating point math?

James Newton-King
  • 48,174
  • 24
  • 109
  • 130
  • 1
    I suppose it would depend on your definition of multiple – D. Ben Knoble Jun 08 '16 at 10:58
  • 3
    It is not a meaningful question. Multiply everything by a 1000 so you can use an integral type like *int* or *long*. Or use an epsilon to call it "close enough". – Hans Passant Jun 08 '16 at 10:58
  • If you were going to multiply to turn values into ints, how would find out how many decimals there are in a double? multipleOf * Math.Pow(10, ?) – James Newton-King Jun 08 '16 at 11:07
  • I've updated my answer as it was missing a check (it does not handle negative values but I think you can easily add that yourself). Here's the most useful article I know of about floating point comparison which may provide you with further insight into this problem: [Comparing Floating Point Numbers, 2012 Edition](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) – keith Jun 08 '16 at 18:55

1 Answers1

5

You would determine if the remainder is below an acceptable tolerance to your problem or if the remainder is very close to your multipleOf:

if (Math.Abs(remainder) < tolerance)
{
   //remainder is negligible so we'll say it's a multiple
}
else if (Math.Abs(multipleOf) - Math.Abs(remainder) < tolerance)
{
   //remainder is almost multiple of divisor so we'll say it's a multiple
}

Only you can decide on a small enough value for tolerance. Sometimes machine epsilon is used for this type of check but it might be too low. If v is very large and multipleOf very small we might say the problem is ill conditioned because the tolerance might need to be so high the results would be useless for the level of accuracy you require in your application. So searching for Conditioning and Precision might be of further interest as well.

keith
  • 5,122
  • 3
  • 21
  • 50