2

I'm attempting Project Euler problem 484. I'm in the beginning stages of the problem and am just searching for patterns in the numbers.

The problem requests me to find an "arithmetic derivative". For example, to find the arithmetic derivative of 60:

60 = 2^2 * 3^1 * 5^1

60' = (2/2 + 1/3 + 1/5) * 60 = 92

I utilized the built in primefac algorithm, and created a method for the arithmetic derivative. Here is my code:

import primefac

def ad(n):
  ans = 0
  for i in set(primefac.primefac(n)):
    ans += 1.0*list(primefac.primefac(n)).count(i)/i
  return n*ans

print ad(30) ,  31.0 // PRINTS 31.0 31.0
print int(ad(30))    // PRINTS 30
print ad(30) == 31.0 // PRINTS False

Python casts 31.0 as an int to 30. Is this a floating point error? What is more perplexing is that ad(30) prints 31.0 but returns False when evaluated against each other.

5
  • What does print(repr(ad(30))) display? And what version of Python are you using? Commented Nov 10, 2017 at 20:08
  • Also, FYI: primefac isn't "built in", it's an external module. Commented Nov 10, 2017 at 20:09
  • Perhaps what you're looking for is round rather than int, or perhaps you shouldn't have any floats as intermediary values in the first place (if you only intend to do exact operations, then you should not be using floats at all because they are approximations) Commented Nov 10, 2017 at 20:09
  • 1
    30.999999999999996 and python 2.7.10 Commented Nov 10, 2017 at 20:10
  • That makes sense. It's just a display issue with print (more accurately, with float.__str__) which I'm fairly sure was addressed somewhere in the 3.0 branch. int will truncate/round down, so everything you're showing makes sense. If you want to test for "equality" with floats, it's best to use some "closeness" test (e.g. Python3.5+ math.isclose) or some similar backport. numpy.isclose() may also be an option. (See also PEP485) Commented Nov 10, 2017 at 20:13

1 Answer 1

2

Yes, this is a floating point issue. There's an easy fix, though... since n will always by definition be evenly divisible by i, you can cut out the floating point math entirely:

def ad(n):
    ans = 0
    for i in set(primefac.primefac(n)):
        ans += n * list(primefac.primefac(n)).count(i) // i
    return ans
Sign up to request clarification or add additional context in comments.

1 Comment

Also, unrelated to this question, but note that you're rerunning primefac, an expensive operation, once for every different factor in n. Better to run it once at the beginning of the function and save the results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.