I have a code which part of it looks like this,
A=(-1//2+(int(math.sqrt(1+8*t)))//2)
if type(A)==int:
print(t)
print(A)
The problem arises when I use "/" to get "A",
Since I am using "/", I always get an extra decimal point. For example 5/5=1.0 or 4/2=2.0 etc, which python interprets it as a float (I am using 3.6.5). Hence whatever the result is my code stuck at line2.
When I use // the same thing happens. I get 5/2=2 which its float actually but it appears as an integer.
Since my code depends on the type of this division how I can solve this problem?
A=(-1//2+(int(math.sqrt(1+8*t)))//2) its a actually the formula for finding the roots of the quadratic equation (where in the equation a=1 and b=1 and c=-2t for ax^2+bx+c) I need only the integer roots with positive values
What you're trying to do won't work. For two integers x and y, x/y is always a float, even if it happens to be integral, and x//y is always an int, even if it has to truncate (throw away) a fractional part. So testing type(A) == int doesn't test for anything except which of the two you used.
There is a method float.is_integer that you can use, and that works fine for integers divided by 2—but it doesn't work once you're using sqrt. Explaining floating-point rounding issues is a big enough job that it takes up a whole paper that's so important that it's been included by reference in multiple language specifications, but the short version is that sqrt could very easily give you a number that's a tiny big bigger or smaller than an integer, so is_integer will give you the wrong answer.
What you probably want to do is something like this:
if math.isclose(A, round(A)):
The round function will round a float to the nearest integer. The isclose function will then check whether the resulting integer is "close enough" to the original float. You should read the docs on isclose to understand exactly what it does, but in this case, I think the default values will be fine, unless you're dealing with huge integers.
Related
In python using // for division forces the result to be an integer. Is there an equivalent for multiplication?
For example, assume I have an integer W which I scale by a float f. It could be nice to have an operator such as .*, so that:
int(W*f)==W.*f
Would be True.
// does not "force the result to be an integer", this may be coincidentally true, but describing the operator in this presumptuous way is (I believe) resulting in you thinking that there should be other analogous features, which there really aren't. // is "floor division", which any type can overload to have any desired behaviour. There is no "floor multiplication" operator. If you want the result of multiplication to be forced to an integer, you've already shown a perfectly acceptable and straightforward way to do this:
int(W*f)
No, and there is unlikely to be one added, for two reasons.
The current options are short and built-in
There is no ambiguity to be resolved
When you take 12/5 you can reasonably want a integer, quotient, or real, all of which are well defined, take different values in python (without infinite floating precision) and behave differently.
When you multiply 12*5, you could also want those three, but the value will be identical.
For something like pi * 100000, you would need to know the type to end up with as well as the resolution technique for e.g. float to integer (floor, ceiling, round closest, round .5 up, round .5 down, bankers rounding). Without strong types this becomes a mess to hand down from above, and easier to delegate to the user and their own needs or preferences.
Is the algorithm used for rounding a float in Python to a specified number of digits specified in any Python documentation? The semantics of round with zero fractional digits (i.e. rounding to an integer) are simple to understand, but it's not clear to me how the case where the number of digits is nonzero is implemented.
The most straightforward implementation of the function that I can think of (given the existence of round to zero fractional digits) would be:
def round_impl(x, ndigits):
return (10 ** -ndigits) * round(x * (10 ** ndigits))
I'm trying to write some C++ code that mimics the behavior of Python's round() function for all values of ndigits, and the above agrees with Python for the most part, when translated to equivalent C++ calls. However, there are some cases where it differs, e.g.:
>>> round(0.493125, 5)
0.49312
>>> round_impl(0.493125, 5)
0.49313
There is clearly a difference that occurs when the value to be rounded is at or very near the exact midpoint between two potential output values. Therefore, it seems important that I try to use the same technique if I want similar results.
Is the specific means for performing the rounding specified by Python? I'm using CPython 2.7.15 in my tests, but I'm specifically targeting v2.7+.
Also refer to What Every Programmer Should Know About Floating-Point Arithmetic, which has more detailed explanations for why this is happening as it is.
This is a mess. First of all, as far as float is concerned, there is no such number as 0.493125, when you write 0.493125 what you actually get is:
0.493124999999999980015985556747182272374629974365234375
So this number is not exactly between two decimals, it's actually closer to 0.49312 than it is to 0.49313, so it should definitely round to 0.49312, that much is clear.
The problem is that when you multiply by 105, you get the exact number 49312.5. So what happened here is the multiplication gave you an inexact result which by coincidence canceled out the rounding error in the original number. Two rounding errors canceled each other out, yay! But the problem is that when you do this, the rounding is actually incorrect... at least if you want to round up at midpoints, but Python 3 and Python 2 behave differently. Python 2 rounds away from 0, and Python 3 rounds towards even least-significant digits.
Python 2
if two multiples are equally close, rounding is done away from 0
Python 3
...if two multiples are equally close, rounding is done toward the even choice...
Summary
In Python 2,
>>> round(49312.5)
49313.0
>>> round(0.493125, 5)
0.49312
In Python 3,
>>> round(49312.5)
49312
>>> round(0.493125, 5)
0.49312
And in both cases, 0.493125 is really just a short way of writing 0.493124999999999980015985556747182272374629974365234375.
So, how does it work?
I see two plausible ways for round() to actually behave.
Choose the closest decimal number with the specified number of digits, and then round that decimal number to float precision. This is hard to implement, because it requires doing calculations with more precision than you can get from a float.
Take the two closest decimal numbers with the specified number of digits, round them both to float precision, and return whichever is closer. This will give incorrect results, because it rounds numbers twice.
And Python chooses... option #1! The exactly correct, but much harder to implement version. Refer to Objects/floatobject.c:927 double_round(). It uses the following process:
Write the floating-point number to a string in decimal format, using the requested precision.
Parse the string back in as a float.
This uses code based on David Gay's dtoa library. If you want C++ code that gets the actual correct result like Python does, this is a good start. Fortunately you can just include dtoa.c in your program and call it, since its licensing is very permissive.
The Python documentation for and 2.7 specifies the behaviour:
Values are rounded to the closest multiple of 10 to the power minus
ndigits; if two multiples are equally close, rounding is done away
from 0.
For 3.7:
For the built-in types supporting round(), values are rounded to the
closest multiple of 10 to the power minus ndigits; if two multiples
are equally close, rounding is done toward the even choice
Update:
The (cpython) implementation can be found floatobjcet.c in the function float___round___impl, which calls round if ndigits is not given, but double_round if it is.
double_round has two implementations.
One converts the double to a string (aka decimal) and back to a double.
The other one does some floating point calculations, calls to pow and at its core calls round. It seems to have more potential problems with overflows, since it actually multiplies the input by 10**-ndigits.
For the precise algorithm, look at the linked source file.
I am relatively new to Python and have encountered a strange issue. I need to calculate a thickness of a tube 't' out of the eqn. which is given below. As expected, "solution" gives 4 possible values of t, of which only one is feasible, being a positive and real value. Two of my four solutions are complex and one is negative. Out of my solution-array of 4 values, I want to take that specific feasible solution and one operation is taking the real part of all values in that array. In taking the real part of one complex solution (sol2.real) out of the solution-array, it gives me always an error, while taking x.real with eg. x=1+2j gives the expected 1. I have noticed that my complex solutions don't have the normal symbol j, but the capital symbol I. The numpy and sympy packages are imported.
import numpy
import simpy
sigma_max=880000000
r_i=0.06
t = Symbol('t')
eqn=sigma_max-((9000*5.5*9.81)/(3.1415*((r_i+t)**2-r_i**2)))-(r_i+t)* \
(((25000*0.5*9.81)**2+(134*9.81)**2)**0.5)/((3.1415/4)*((r_i+t)**4-r_i**4))
solution=solve(eqn, t)
print(solution)
sol2=solution[2]
x=1+2j
print(x.real)
print(sol2.real)
The error I encounter with the "print(sol2.real)" command is:
'Add' object has no attribute 'real'
Could someone explain me what my fault is or where it goes wrong?
Many thanks in advance
Assuming the rest of your actual code is doing something reasonable, your problem is that you're mixing up sympy expressions with normal Python numbers.
Your sol2 is an expression. Sure, it looks like a number, but that's true for any expression that has nothing but constant values in it; it's still not a Python complex, any more than sympy.pi is a Python float.
What you probably want here is the re function:
>>> print(sympy.re(sol2))
-0.0720141606282290
(Of course this still isn't a Python float, it's still a sympy expression. But it prints out what I think you want to print out.)
Or, if you're done doing symbolic computation and want to convert to raw Python values, you can do that this:
>>> print(float(sympy.re(sol2)))
-0.07201416062822902
>>> print(complex(sol2).re)
-0.07201416062822902
Either of these is getting a Python float—along with any rounding errors that come from converting an exact symbolic value, or higher-precision decimal value, to float, of course.
The problem is that the items in solution are classes of sympy (e.g. type(solution[2]) is <class 'sympy.core.add.Add'>, which doesn't have an attribute real.
You can fix this by changing print(sol2.real) to print(complex(sol2).real)
So I have a list of tuples of two floats each. Each tuple represents a range. I am going through another list of floats which represent values to be fit into the ranges. All of these floats are < 1 but positive, so precision matter. One of my tests to determine if a value fits into a range is failing when it should pass. If I print the value and the range that is causing problems I can tell this much:
curValue = 0.00145000000671
range = (0.0014500000067055225, 0.0020968749796738849)
The conditional that is failing is:
if curValue > range[0] and ... blah :
# do some stuff
From the values given by curValue and range, the test should clearly pass (don't worry about what is in the conditional). Now, if I print explicitly what the value of range[0] is I get:
range[0] = 0.00145000000671
Which would explain why the test is failing. So my question then, is why is the float changing when it is accessed. It has decimal values available up to a certain precision when part of a tuple, and a different precision when accessed. Why would this be? What can I do to ensure my data maintains a consistent amount of precision across my calculations?
The float doesn't change. The built-in numberic types are all immutable. The cause for what you're observing is that:
print range[0] uses str on the float, which (up until very recent versions of Python) printed less digits of a float.
Printing a tuple (be it with repr or str) uses repr on the individual items, which gives a much more accurate representation (again, this isn't true anymore in recent releases which use a better algorithm for both).
As for why the condition doesn't work out the way you expect, it's propably the usual culprit, the limited precision of floats. Try print repr(curVal), repr(range[0]) to see if what Python decided was the closest representation of your float literal possible.
In modern day PC's floats aren't that precise. So even if you enter pi as a constant to 100 decimals, it's only getting a few of them accurate. The same is happening to you. This is because in 32-bit floats you only get 24 bits of mantissa, which limits your precision (and in unexpected ways because it's in base2).
Please note, 0.00145000000671 isn't the exact value as stored by Python. Python only diplays a few decimals of the complete stored float if you use print. If you want to see exactly how python stores the float use repr.
If you want better precision use the decimal module.
It isn't changing per se. Python is doing its best to store the data as a float, but that number is too precise for float, so Python modifies it before it is even accessed (in the very process of storing it). Funny how something so small is such a big pain.
You need to use a arbitrary fixed point module like Simple Python Fixed Point or the decimal module.
Not sure it would work in this case, because I don't know if Python's limiting in the output or in the storage itself, but you could try doing:
if curValue - range[0] > 0 and...
I am depending on some code that uses the Decimal class because it needs precision to a certain number of decimal places. Some of the functions allow inputs to be floats because of the way that it interfaces with other parts of the codebase. To convert them to decimal objects, it uses things like
mydec = decimal.Decimal(str(x))
where x is the float taken as input. My question is, does anyone know what the standard is for the 'str' method as applied to floats?
For example, take the number 2.1234512. It is stored internally as 2.12345119999999999 because of how floats are represented.
>>> x = 2.12345119999999999
>>> x
2.1234511999999999
>>> str(x)
'2.1234512'
Ok, str(x) in this case is doing something like '%.6f' % x. This is a problem with the way my code converts to decimals. Take the following:
>>> d = decimal.Decimal('2.12345119999999999')
>>> ds = decimal.Decimal(str(2.12345119999999999))
>>> d - ds
Decimal('-1E-17')
So if I have the float, 2.12345119999999999, and I want to pass it to Decimal, converting it to a string using str() gets me the wrong answer. I need to know what are the rules for str(x) that determine what the formatting will be, because I need to determine whether this code needs to be re-written to avoid this error (note that it might be OK, because, for example, the code might round to the 10th decimal place once we have a decimal object)
There must be some set of rules in python's docs that hopefully someone here can point me to. Thanks!
In the Python source, look in "Include/floatobject.h". The precision for the string conversion is set a few lines from the top after an comment with some explanation of the choice:
/* The str() precision PyFloat_STR_PRECISION is chosen so that in most cases,
the rounding noise created by various operations is suppressed, while
giving plenty of precision for practical use. */
#define PyFloat_STR_PRECISION 12
You have the option of rebuilding, if you need something different. Any changes will change formatting of floats and complex numbers. See ./Objects/complexobject.c and ./Objects/floatobject.c. Also, you can compare the difference between how repr and str convert doubles in these two files.
There's a couple of issues worth discussing here, but the summary is: you cannot extract information that is not stored on your system already.
If you've taken a decimal number and stored it as a floating point, you'll have lost information, since most decimal (base 10) numbers with a finite number of digits cannot be stored using a finite number of digits in base 2 (binary).
As was mentioned, str(a_float) will really call a_float.__str__(). As the documentation states, the purpose of that method is to
return a string containing a nicely printable representation of an object
There's no particular definition for the float case. My opinion is that, for your purposes, you should consider __str__'s behavior to be undefined, since there's no official documentation on it - the current implementation can change anytime.
If you don't have the original strings, there's no way to extract the missing digits of the decimal representation from the float objects. All you can do is round predictably, using string formatting (which you mention):
Decimal( "{0:.5f}".format(a_float) )
You can also remove 0s on the right with resulting_string.rstrip("0").
Again, this method does not recover the information that has been lost.