1

In order to sync my iPod and my local music repository, I created a unique key for each track using its metadata. The unique track consists of the track's following metadata fields: artist, album, track number, duration. The iPod saves the track's duration in milliseconds, but my local repository saves it in seconds. For example: 437590 milliseconds on iPod is 438 seconds in my Local repository.

When I divide the ipod's track duration by 1000 I get 437. I tried using round(), but round (b.tracklen/1000) prints 437.

I can hack this by checking math.ceil(), math.floor() for the iPod duration if there is no match but it's a lousy solution.

What is the best approach to this issue?

4
  • 3
    Sounds to me like you just need to use a threshold. Something like if abs(numA - numB) < thresh: everything_looks_good(); Commented Jul 25, 2011 at 15:40
  • 3
    Try: round(b.tracklen/1000.0) Commented Jul 25, 2011 at 15:41
  • @kwatford is right for Python 2 - you need floating point division. For Python 3, this problem won't happen - the semantics of division has changed, and there is a new // operator for integer division. Commented Jul 25, 2011 at 15:51
  • Actually, after trying the round options I still have some missing songs which I couldn't track down. so I'm now implementing the math.floor() and math.ceil() and I'll soon see if it makes a difference. Commented Jul 25, 2011 at 18:14

4 Answers 4

6

Your round call is giving the wrong result as you're dividing by 1000, instead of 1000.0

>>> round(437590/1000.0)
438.0
Sign up to request clarification or add additional context in comments.

3 Comments

thanks, that's solved the issue. is there any reference available on this ? I've read round() in the documentation but I don't remember notes on something similar
@Liron - that's because your issue is the semantics of the division operator. What round sees isn't the division computation, only the result, which (for integer division) is already truncated to 437. Round 437 to the nearest whole number and you get 437.
Also note that this is only true for Python2 and in Python3 luckily the semantics of the division have changed, which makes this a non issue.
2

You are experiencing Python 2's integer division. When you divide two integers, Python (and many other languages) throw away the remainder. You'll want to divide by a float instead of an integer, as Dogbert indicated.

4 Comments

If you say "Python 2", I'll +1 - Python 3 behaves differently. Not a change I approve of, as it happens - I don't much care how a particular language chooses to handle division of integers, but I do care when a language changes the semantics of a basic arithmetic operator. Still, it's done now, and it does avoid this kind of problem.
Okay, thanks, good to know; changed it. Yeah, they did some controversial things in 3.
@Steve314 It was never a clever idea to use integer division in a dynamically typed language as a general rule, because it leads to exactly this kind of problems. And the 2to3 transition tool takes care of it for existing code.
@Voo - some people expect what you say. Some people expect an integer divided by an integer to give an integer - arithmetic operators returning the same type as their arguments. A lot of languages use that latter convention, so newbies are probably going to have to learn it at some point. There's even a math (abstract algebra) argument that it's exactly the right thing to do. Overall, it's swings and roundabouts, but changing semantics of division around two decades into the life of a language is still a bit crazy, however well it's managed. Not everyone will know to run that tool.
0

Rounding the result of an integer division is very easy: (n+(d/2))/d. In your case:

def RoundedDivide(value, divisor):
    return (value + (divisor/2)) / divisor

>>> RoundedDivide(437590, 1000)
438

5 Comments

Is there anybody out there who can explain the downvote? I thought this answered the question directly, while avoiding all the problems that can be encountered with floating point numbers.
@hop, are you aware of a simpler way to do integer division with rounding? Please share.
this would be a fine answer… to another question.
@hop, how is it not relevant? The question states that round didn't give the answer they were looking for, and I provided a version that does. It will do so with a higher degree of confidence than the accepted answer, because it's not subject to the representation errors of floating point numbers.
+1 for a solution (which does solve the problem) which is different and worth considering.
-2

Honestly, I think you nailed it already with the floor and ceil calls, but for somplicity you might want to do floor((ipodtime/1000)+1) == localrepostime to check equality since the ipod time seems to round down no matter what.

Comments

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.