Why is my integer viewed by python as a complex number? - python

I just started a course in Python and trying this code:
import math
c = int(input('Enter number: '))
a = 1
counter = 0
while counter != 2:
a = a + 1
b = round((c-(a**3))**(1/3.0))
if a < b and a**3 + b**3 == c:
counter = counter + 1
print(a,b)
My problem is that python cant round the 'b' since it is viewed as a complex number...
The program is supposed to find two sets of a & b that satisfie a^3+b^3=c, any feed back on my code is appreciated.

Basically, raising a negative number to a fractional power always yields a complex number. For example, sqrt(-1) (which is (-1)**(1/2)), is clearly complex.
So, if you try to raise -8 to the 1/3th power, you'll get a complex number. For example:
a = (-8)**(1/3)
print(a)
print(a**3)
Will print
(1.0000000000000002+1.7320508075688772j)
(-8+3.1086244689504383e-15j)
That gives back -8 when raised to the 3rd power, give or take some rounding.
This rounding is the real issue here. You could well say that -8 to the power 1/3 is -2, as -2 to the 3rd power is -8. However - and this is the crux - that only works if the power is actually 1/3. In a floating point number it will actually be 0.33333 (with some more threes), which is not exactly the same. Hence the exponentiation is done with complex numbers.
You'll either have to work with complex numbers, or rewrite your maths to not use fractional powers of negative numbers.

You need to guard your computation against a^3 being larger than c; that's what returns a complex number. Make sure that you move the increment of a, so that the while uses that same value. Perhaps
while counter != 2 and c >= a**3:
b = round((c-(a**3))**(1/3.0))
if a < b and a**3 + b**3 == c:
counter = counter + 1
print(a,b)
a = a + 1
Output with c = 1729, the Ramanujan-Hardy number:
1 12
9 10
Also, why are you waiting for two solutions? "counter" puzzles me ... you could use a Boolean flag if you need only one solution.

Related

How To Find Division Without Using Division Operator In Python?

I've Found How to do it for normal numbers which gives quotient above 1
How to find value for which we will get quotient below 1
For example if 28 divided by 500 it gives 0.056
How to implement above example without using division operator
There is not a way to do this, unless you count reciprocals. However, these are fractions which means they use divide.
For example:
>>> 30 / 5 # original calculation
6
>>> 30 * 0.2 # using the reciprocal of 5 – but no division sign visible!
6
However, this option clearly uses division. If you don't see it, here's how:
def divide(x, y):
return x * (1/y)
Because to make a number a reciprocal, you have to divide. But take into consideration that every whole number uses divide: 5 = 5/1, so it's just the same with a different denominator...
#in this case 18/2
e=18
t=2
o=0
l=t
count=0
t=0
for i in range(0,e):
t+=l
count+=1
if t==e:
o=1
print(count)
break
if (t+l) > e:
break
if o!=1:
c=e-t
print(count,'reminder of',c)
You indicate you already have something without division that handles cases with quotients greater than 1. If so, you can reduce your as yet unsolved case like 28/500 by doing 2800/500 and then getting around dividing by 100 (at least directly) by adding two decimal places. Since you want two significant figures, it seems, you actually would want to do 28000/500, at least if you did things as I am guessing you did.
Here's how that plays out in code:
def algorithm_you_already_have(a, b):
"""I assume a>b>0 you can add logic to handle negatives or check for b == 0
you say you already have something that works if a divided by b is greater than 1
Here is one thing you might have done, repeated subtraction"""
assert a > b # this was only working and for use when quotient was greater than 1, you said
assert b > 0 # cannot divide by 0, and not dealing with negatives here, could higher up
result = 0
while a >= b:
a -= b
result += 1
if a + a >= b: # round up if remainder is at least half of divisor
result += 1
return result
# assumes positives, you can add cases as needed
def algorithm_you_need(a, b):
assert a > 0
assert b > 0
temp_result = 0
if a == b:
return 1
if a > b:
return algorithm_you_already_have(a, b)
# still here, then a < b, which is the new case you need
places_shifted = 0
while a < b:
a *= 10
places_shifted += 1
if a == b:
temp_result = 1
else:
temp_result = algorithm_you_already_have(10 * a, b) # times 10 to get a second figure as desired
# but do not count is as a shift, because you are putting the next figure, if any, beyond the first
# process as string
temp_result = str(temp_result)
while places_shifted > 1:
temp_result = '0' + temp_result
places_shifted -= 1
temp_result ="0." + temp_result
return float(temp_result)
print(algorithm_you_need(28,500))

While statement in python

while b:
n.append(int(b%10))
b=b/10
return n
Here the while statement is not stopping even when b=0, what is the problem with this?
Let's simplify your while loop and remove the unnecessary parts:
while b:
b = b/10
print(b)
What this does is, it takes a given b, divides it by 10, and assigns this as b. Now the "divide by 10" part is tricky.
If you are using Python 2, it works as an integer division:
19/10 = 1
Let's divide this one more time:
1/10 = 0
But in Python 3, this is an actual, proper division:
19/10 = 1.9
Let's divide this one also one more time:
1.9/10 = 0.19
So in Python 2, your loop will keep rounding the division down, and you will reach 0 eventually. But in Python 3, you will keep dividing your float properly, and will never reach 0. This will mean that your while will never terminate.
Solution: If you want to end up at 0 eventually through integer division so that your loop ends at some point, you can use a//b in Python 3 to get the same behavior of a/b in Python 2.
The most efficient way to compute the reminder and the integer quotient is divmod.
while b:
b, m = divmod(b, 10)
n.append(m)
This loop stops for non-negative b.
I think you want to do integer division, if that is the case your code should have // instead of /
while b:
n.append(int(b%10))
b=b//10
return n
As neither valid answer is accepted, I'll offer the alternative solution, which is to change the stopping condition of the while loop. This lets you keep your floating point division should you need it for some case not in the original question. You can also do the integer division with the shorthand b //= 10.
while int(b): # Or more explicitly: while bool(int(b)):
n.append(int(b%10))
b /= 10
return n

Finding max of ANDing between two numbers in Python

I am a beginner to Python coding. I have two numbers A and B from user.
My problem is to find the max(P AND Q) where A <= P < Q <= B
I have two solutions right now for this.
Solution 1 : # ANDing with all combinations, This solution works if combinations are less. For higher values, it throws memory exceeding error.
given = raw_input()
n= list(map(int,given.split()))
A = n[0]
B = n[1]
newlist = range(B+1)
# print newlist
# Finding all combinations
comb = list(itertools.combinations(newlist,2))
# print comb
# ANDing
l = []
for i in com:
x = i[0] & i[1]
l.append(x)
# print l
print max(l)
Solution 2: After observing many input-outputs, when B == Odd, max(value) = B-1 and for B == Even, max(value) = B-2.
given = raw_input()
n= list(map(int,given.split()))
A = n[0]
B = n[1]
if B % 2 == 0:
print (B - 2)
else:
print (B -1)
According to the problem statement I am not using any ANDing for Solution 2. Still I am getting correct output.
But I am looking for much easier and Pythonic logic. Is there any other way/logic to solve this?
Your second solution is the optimal solution. But why? First, consider that a logical AND is performed on the binary representation of a number, and it is only possible to produce a number less than or equal to the smallest operand of the AND operator. For instance, 9 is represented as 1001, and there is no number that 9 can be anded with that produces a number higher than 9. Indeed, the only possible outputs for anding another number with 9 would be 9, 8, 1 and 0. Or alternatively, the biggest result from anding 9 with a number smaller than 9, is 9 less its least significant bit (so 8). If you're not sure of the binary representation of a number you can always use the bin function. eg. bin(9) => '0b1001'.
Let's start with odd numbers (as they're the easiest). Odd numbers are easy because they always have a bit in the unit position. So the maximum possible number that we can get is B less that bit in the unit position (so B - 1 is the maximum). For instance, 9 is represented as 1001. Get rid of the unit bit and we have 1000 or 8. 9 and 8 == 8, so the maximum result is 8.
Now let's try something similar with evens. For instance, 14 is represented as 1110. The maximum number we can get from anding 14 with another number would be 1100 (or 12). Like with odds, we must always lose one bit, and the smallest possible bit that can be lost is the bit in 2s position. Here, we're fortunate as 14 already as a bit in the 2s position. But what about numbers that don't? Let's try 12 (represented as 1100). If we lost the smallest bit from 12, we would have 1000 or 8. However, this is not the maximum possible. And we can easily prove this, because the maximum for 11 is 10 (since we have shown the maximum for an odd number is the odd number less 1).
We have already shown that the biggest number that can be produced from anding two different numbers is the bigger number less its least significant bit. So if that bit has a value of 2 (in the case of 14), when we can just lose that bit. If that bit has a value higher than 2 (in the case of 12), then we know the maximum is the maximum of the biggest odd number less than B (which is 1 less than the odd number and 2 less than B).
So there we have it. The maximum for an odd number is the number less 1. And the maximum for an even number is the number less 2.
def and_max(A, B): # note that A is unused
if B & 1: # has a bit in the 1 position (odd)
P, Q = B - 1, B
else:
P, Q = B - 2, B - 1
# print("P = ", P, "Q = ", Q)
return P & Q # essentially, return P
Note that none of this covers negative numbers. This is because most representations of negative numbers are in two's complement. What this means is that all negative numbers are represented as constant negative number plus a positive number. For instance, using an 4-bit representation of integers the maximum possible number would be 0111 (or 7, 4 + 2 + 1). Negative numbers would be represented as -8 plus some positive number. This negative part is indicated by a leading bit. Thus -8 is 1000 (-8 + 0) and -1 is 1111 (-8 + 7). And that's the important part. As soon as you have -1, you have an all 1s bitmask which is guaranteed to lose the negative part when anded with a positive number. So the maximum for max(P and Q) where A <= P < Q <= B and A < 0 is always B. Where B < 0, we can no longer lose the negative bit and so must maximise the positive bits again.
I think this should work:
given = raw_input()
a, b = tuple(map(int,given.split()))
print(max([p & q for q in range(a,b+1) for p in range(a,q)]))
long a,b,c,ans;
for(int i=0;i<n;i++){
a=s.nextLong();
b=s.nextLong();
if(b%2==0)
ans=b-2;
else
ans=b-1;
if(ans>=a)
System.out.println(ans);
else
System.out.println(a&b);
}

Python Partial Harmonics

Could someone help check why the result is always one and let me know what I did wrong? Thanks
Correct result should be: 1/1 + 1/2 + 1/3 == 1.83333333333.
x = int(input("Enter n: "))
assert x > 0, "n must be greater than zero!"
def one_over_n(x):
result = 0
for n in range(x):
n += 1
result += 1 / n
return result
r = one_over_n(x)
print("one_over_n( {0:d} ): {1:f}" .format(x, r))
It will work correctly on python 3, but not in python 2
>>> 1/2
0
That means you are just adding zeroes, to one. You will need to change either numerator or denominator to a float number e.g. 1/2.0, so change your code to
result += 1.0 / n
See Pep 238 to see why it was changed in python 3.
btw floating point numbers can't represent all fractions, so if you are just adding fractions, you can use Fraction class e.g.
>>> from fractions import Fraction as F
>>> F(1,1) + F(1,2) + F(1,3)
Fraction(11, 6)
As an alternative, to force Python 2 perform division as you expect (rather than integer division), add:
from __future__ import division

Random number function python that includes 1?

I am new to Python and am trying to create a program for a project- firstly, I need to generate a point between the numbers 0-1.0, including 0 and 1.0 ([0, 1.0]). I searched the python library for functions (https://docs.python.org/2/library/random.html) and I found this function:
random.random()
This will return the next random floating point number in the range [0.0, 1.0). This is a problem, since it does not include 1. Although the chances of actually generating a 1 are very slim anyway, it is still important because this is a scientific program that will be used in a larger data collection.
I also found this function:
rand.randint
This will return an integer, which is also a problem.
I researched on the website and previously asked questions and found that this function:
random.uniform(a, b)
will only return a number that is greater than or equal to a and less than b.
Does anyone know how to create a random function on python that will include [0, 1.0]?
Please correct me if I was mistaken on any of this information. Thank you.
*The random numbers represent the x value of a three dimensional point on a sphere.
Could you make do with something like this?
random.randint(0, 1000) / 1000.0
Or more formally:
precision = 3
randomNumber = random.randint(0, 10 ** precision) / float(10 ** precision)
Consider the following function built on top of random.uniform. I believe that the re-sampling approach should cause all numbers in the desired interval to appear with equal probability, because the probability of returning candidate > b is 0, and originally all numbers should be equally likely.
import sys
import random
def myRandom(a, b):
candidate = uniform.random(a, b + sys.float_info.epsilon)
while candidate > b:
candidate = uniform.random(a, b + sys.float_info.epsilon)
return candidate
As gnibbler mentioned below, for the general case, it may make more sense to change both the calls to the following. Note that this will only work correctly if b > 0.
candidate = uniform.random(a, b*1.000001)
Try this:
import random
random.uniform(0.0, 1.0)
Which will, according to the documentation [Python 3.x]:
Return a random floating point number N such that a <= N <= b for a <= b and b <= N <= a for b < a.
Notice that the above paragraph states that b is in fact included in the range of possible values returned by the function. However, beware of the second part (emphasis mine):
The end-point value b may or may not be included in the range depending on floating-point rounding in the equation a + (b-a) * random().
For floating point numbers you can use numpy's machine limits for floats class to get the smallest possible value for 64bit or 32bit floating point numbers. In theory, you should be able to add this value to b in random.uniform(a, b) making 1 inclusive in your generator:
import numpy
import random
def randomDoublePrecision():
floatinfo = numpy.finfo(float)
epsilon = floatinfo.eps
a = random.uniform(0, 1 + eps)
return a
This assumes that you are using full precision floating point numbers for your number generator. For more info read this Wikipedia article.
Would it be just:
list_rnd=[random.random() for i in range(_number_of_numbers_you_want)]
list_rnd=[item/max(list_rnd) for item in list_rnd]
Generate a list of random numbers and divide it by its max value. The resulting list still flows uniform distribution.
I've had the same problem, this should help you.
a: upper limit,
b: lower limit, and
digit: digit after comma
def konv_des (bin,a,b,l,digit):
des=int(bin,2)
return round(a+(des*(b-a)/((2**l)-1)),digit)
def rand_bin(p):
key1 = ""
for i in range(p):
temp = str(random.randint(0, 1))
key1 += temp
return(key1)
def rand_chrom(a,b,digit):
l = 1
eq=False
while eq==False:
l += 1
eq=2**(l-1) < (b-a)*(10**digit) and (b-a)*(10**digit) <= (2**l)-1
return konv_des(rand_bin(l),a,b,l,digit)
#run
rand_chrom(0,1,4)

Categories

Resources