Can anyone explain how the modulo operator works in Python?
I cannot understand why 3.5 % 0.1 = 0.1.
Can anyone explain how the modulo operator works in Python? I cannot understand why
Share
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
Actually, it’s not true that
3.5 % 0.1is0.1. You can test this very easily:In actuality, on most systems,
3.5 % 0.1is0.099999999999999811. But, on some versions of Python,str(0.099999999999999811)is0.1:Now, you’re probably wondering why
3.5 % 0.1is0.099999999999999811instead of0.0. That’s because of the usual floating point rounding issues. If you haven’t read What Every Computer Scientist Should Know About Floating-Point Arithmetic, you should—or at least the brief Wikipedia summary of this particular issue.Note also that
3.5/0.1is not34, it’s35. So,3.5/0.1 * 0.1 + 3.5%0.1is3.5999999999999996, which isn’t even close to3.5. This is pretty much fundamental to the definition of modulus, and it’s wrong in Python, and just about every other programming language.But Python 3 comes to the rescue there. Most people who know about
//know that it’s how you do “integer division” between integers, but don’t realize that it’s how you do modulus-compatible division between any types.3.5//0.1is34.0, so3.5//0.1 * 0.1 + 3.5%0.1is (at least within a small rounding error of)3.5. This has been backported to 2.x, so (depending on your exact version and platform) you may be able to rely on this. And, if not, you can usedivmod(3.5, 0.1), which returns (within rounding error)(34.0, 0.09999999999999981)all the way back into the mists of time. Of course you still expected this to be(35.0, 0.0), not(34.0, almost-0.1), but you can’t have that because of rounding errors.If you’re looking for a quick fix, consider using the
Decimaltype:This isn’t a magical panacea — for example, you’ll still have to deal with rounding error whenever the exact value of an operation isn’t finitely representable in base 10 – but the rounding errors line up better with the cases human intuition expects to be problematic. (There are also advantages to
Decimaloverfloatin that you can specify explicit precisions, track significant digits, etc., and in that it’s actually the same in all Python versions from 2.4 to 3.3, while details aboutfloathave changed twice in the same time. It’s just that it’s not perfect, because that would be impossible.) But when you know in advance that your numbers are all exactly representable in base 10, and they don’t need more digits than the precision you’ve configured, it will work.