3

Consider the following code snippet in Python:

m = int(math.sqrt(n)) 

For n = 25, it should give m = 5 (and it does in my shell). But from my C experience I know that using such expression is a bad idea, as sqrt function may return a slightly lower value than the real value, and then after rounding i may get m = 4 instead of m = 5. Is this limitation also involved in python? And if this is the case, what is be the best way to write such expressions in python? What will happen if I use Java or C#? Besides, if there is any inaccuracy, what factors controls the amount of it?

4
  • 1
    are you sure that's a python code snippet? It looks like you are trying to typecast, you probably should write it like this: m = int(math.sqrt(n)), which is equivalent to what you wrote, but only because (int) --> int and then you call int with the parentheses around the next part of your statement. Commented Aug 13, 2012 at 6:56
  • Since we don't have control over math.sqrt the only thing you can do is to either write your own implementation of math.sqrt or write your own implementation of casting to integer. Commented Aug 13, 2012 at 7:00
  • @JeffTratner Sorry.. I'm new to python. I wrote it as I've done in C.. I'm correcting it. Commented Aug 13, 2012 at 7:01
  • 1
    Look up any question on float accuracy. Any question, as these problems are entirely language-agnostic, and have very little to do with sqrt specifically. Commented Aug 13, 2012 at 7:03

3 Answers 3

7

For proper rounding, use round(); it rounds to the nearest whole number, but returns a float. Then you may construct an int from the result.

(Most probably your code is not performance-critical and you will never notice any slowdown associated with round(). If you do, you probably should be using numpy anyway.)

Sign up to request clarification or add additional context in comments.

1 Comment

Note that round (as well as floor, ceil, and trunc) gives an int from Py3.
3

If you are very concerned with the accuracy of sqrt, you could use the decimal.Decimal class from the standard library, which provides its own sqrt function. The Decimal class can be set to greater precision than regular Python floats. That said, it may not matter if you are rounding anyways. The Decimal class results in exact numbers (from the docs):

The exactness [of Decimal] carries over into arithmetic. In decimal floating point, 0.1 + 0.1 + 0.1 - 0.3 is exactly equal to zero. In binary floating point, the result is 5.5511151231257827e-017. While near to zero, the differences prevent reliable equality testing and differences can accumulate. For this reason, decimal is preferred in accounting applications which have strict equality invariants.

6 Comments

All the solutions are good but I'm marking is accepted as it points to a generic way from getting over floating point inaccuracy in python.
decimal is also floating point numbers, and thus also inexact. It is exact only for rational numbers whose rendering in base 10 needs at most as much precision as the current context permits. It is not exact (can be made to though) when you need more precision than that, and it is not exact whenever an irrational number enters. Try sqrt(2)**2 with decimals (spoiler: it is not 2 at default precision). The only reason to prefer decimal floating point numbers is that some applications (e.g. finance) have already been doing the same truncation for longer than computers exist.
I actually meant its gives accuracy in such cases when I can't really afford values like 4.999999995 or 5.00000002 :)
@Rafi That's right, it will give you 4.99999999999999999999999999995 instead. :)
@Rafi From the python help: "Decimal floating point has finite precision with arbitrarily large bounds. The purpose of this module is to support arithmetic using familiar schoolhouse rules and to avoid some of the tricky representation issues associated with binary floating point." The main advantage, in my opinion, is user definable precision and bounds.
|
2

The solution is easy. If you're expecting an integer result, use int(math.sqrt(n)+.1). If the value is a little more or less than the integer result, it will round to the correct value.

3 Comments

@warwaruk Ooops, sorry missed the dot in .1. Yeah, this might work.
@delnan: Not a hack at all, acknowledging that floating point math is inaccurate and compensating appropriately is key to numerical methods. If one didn't do this there'd be threshold problems near the theoretical value. This code just says that we expect the result to be correct to +/- .1.
I'm not saying it isn't working, and know fully well why it works. I'm saying it is an inelegant workaround to the inaccuracy of floating point values (and may also fail -- namely for very large values -- though that doesn't matter much) and I'd prefer a more elegant solution - such as not using floating point numbers in a context that requires more precision than they offer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.