Output showing 0 for random() function - python-3.x

So, I have this battle scenario here:
def band_attack():
global new_ship
print('Bandits attack!')
s.sleep(1)
c = r.random()
if c < 0.5:
print('Bandits missed!')
elif 0.5 < c < 0.7:
c = r.random()
new_ship = new_ship - int(c)
print('Your ship was hit for', c, 'damage!')
print('Your ship now has', int(new_ship), 'health!')
else:
new_ship = new_ship - int(c)
print('Critical strike! You were hit for', c, 'damage!')
print('Your ship now has', int(new_ship), 'health!')
if new_ship <= 0:
print('You\'ve been destroyed!')
else:
Fight.band_fight()
Fight is the class holding all the battle functions, r is the random module, s is the time module, band_attack is a function where you attack.
I want the damage obviously to be whole numbers above 0, hence why I turn the random function output to an integer.
It should be outputting a number greater than 0, or if it is 0, should just be a miss, but I'm clearly missing something. Maybe someone else can figure out what I'm missing?

The call to random.random() will always return a floating-point number in the range [0.0, 1.0) as per the documentation.
When you cast the result to int (by calling the int(c)), you are asking for the integer part of that float which is always equal to zero for floats in that range.
There are two ways to fix this: either multiply the result of random.random() by 10 or use the random.randint(a, b), which returns a random integer N, such that a <= N <= b. You will need to adjust your conditions accordingly.
You mentioned in the comments that you are worried about seeding the random number generator when using random.randint(a, b) but since the seed function affects the module's random number generator itself all functions (randint, choice, randrange) will behave as expected.

The random() function from the random module (which I assume is what you named r) returns a float between 0 and 1. You can't pass a float into int(). The best alternative would be to use either randint(x, y) (where x and y denote the range in which you want your random damage to be), or stick to random() and mulitply it by the upper limit of that intended range.

Related

how to generate random numbers between closed interval [0,1]?

I need to get soma random values between closed interval [0,1] rather than opened interval. Is there any way this can be done?
Is this ok?
You can use:
random.uniform(0, 1)
Note: When calling N = random.uniform(a, b), the behaviour is always that a <= N <= b but the end-point value b may or may not be included in the range depending on floating-point rounding.
See https://docs.python.org/3/library/random.html?highlight=uniform#random.uniform
First, try: import random (random.randint(0,10**6)*1.0 /10**6)
This will give you full floating point precision.
Otherwise, try:
import decimal
def randfloat():
decimal.getcontext().prec = 10 # 10 decimal points enough?!
return decimal.Decimal(0) + decimal.Decimal(random.uniform(0, 1))
# this should include both boundaries as float gets close enough to 1 to make decimal round
>>> decimal.Decimal(0) + decimal.Decimal(0.99999999999)
Decimal('1.000000000')
while uniform() apparently guarantees the inclusion of the lower boundary

Python infinite recursion with formula

### Run the code below and understand the error messages
### Fix the code to sum integers from 1 up to k
###
def f(k):
return f(k-1) + k
print(f(10))
I am confused on how to fix this code while using recursion, I keep getting the error messages
[Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded
Is there a simple way to fix this without using any while loops or creating more than 1 variable?
A recursion should have a termination condition, i.e. the base case. When your variable attains that value there are no more recursive function calls.
e.g. in your code,
def f(k):
if(k == 1):
return k
return f(k-1) + k
print(f(10))
we define the base case 1, if you want to take the sum of values from n to 1. You can put any other number, positive or negative there, if you want the sum to extend upto that number. e.g. maybe you want to take sum from n to -3, then base case would be k == -3.
Python doesn't have optimized tail recursion. You f function call k time. If k is very big number then Python trow RecursionError. You can see what is limit of recursion via sys.getrecursionlimit and change via sys.setrecursionlimit. But changing limit is not good idea. Instead of changing you can change your code logic or pattern.
Your recursion never terminates. You could try:
def f(k):
return k if k < 2 else f(k-1) + k
print(f(10))
You are working out the sum of all of all numbers from 1 to 10 which in essence returns the 10th triangular number. Eg. the number of black circles in each triangle
Using the formula on OEIS gives you this as your code.
def f(k):
return int(k*(k+1)/2)
print(f(10))
How do we know int() doesn't break this? k and k + 1 are adjacent numbers and one of them must have a factor of two so this formula will always return an integer if given an integer.

math.sqrt function python gives same result for two different values [duplicate]

Why does the math module return the wrong result?
First test
A = 12345678917
print 'A =',A
B = sqrt(A**2)
print 'B =',int(B)
Result
A = 12345678917
B = 12345678917
Here, the result is correct.
Second test
A = 123456758365483459347856
print 'A =',A
B = sqrt(A**2)
print 'B =',int(B)
Result
A = 123456758365483459347856
B = 123456758365483467538432
Here the result is incorrect.
Why is that the case?
Because math.sqrt(..) first casts the number to a floating point and floating points have a limited mantissa: it can only represent part of the number correctly. So float(A**2) is not equal to A**2. Next it calculates the math.sqrt which is also approximately correct.
Most functions working with floating points will never be fully correct to their integer counterparts. Floating point calculations are almost inherently approximative.
If one calculates A**2 one gets:
>>> 12345678917**2
152415787921658292889L
Now if one converts it to a float(..), one gets:
>>> float(12345678917**2)
1.5241578792165828e+20
But if you now ask whether the two are equal:
>>> float(12345678917**2) == 12345678917**2
False
So information has been lost while converting it to a float.
You can read more about how floats work and why these are approximative in the Wikipedia article about IEEE-754, the formal definition on how floating points work.
The documentation for the math module states "It provides access to the mathematical functions defined by the C standard." It also states "Except when explicitly noted otherwise, all return values are floats."
Those together mean that the parameter to the square root function is a float value. In most systems that means a floating point value that fits into 8 bytes, which is called "double" in the C language. Your code converts your integer value into such a value before calculating the square root, then returns such a value.
However, the 8-byte floating point value can store at most 15 to 17 significant decimal digits. That is what you are getting in your results.
If you want better precision in your square roots, use a function that is guaranteed to give full precision for an integer argument. Just do a web search and you will find several. Those usually do a variation of the Newton-Raphson method to iterate and eventually end at the correct answer. Be aware that this is significantly slower that the math module's sqrt function.
Here is a routine that I modified from the internet. I can't cite the source right now. This version also works for non-integer arguments but just returns the integer part of the square root.
def isqrt(x):
"""Return the integer part of the square root of x, even for very
large values."""
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = (1 << (a+b)) - 1
while True:
y = (x + n//x) // 2
if y >= x:
return x
x = y
If you want to calculate sqrt of really large numbers and you need exact results, you can use sympy:
import sympy
num = sympy.Integer(123456758365483459347856)
print(int(num) == int(sympy.sqrt(num**2)))
The way floating-point numbers are stored in memory makes calculations with them prone to slight errors that can nevertheless be significant when exact results are needed. As mentioned in one of the comments, the decimal library can help you here:
>>> A = Decimal(12345678917)
>>> A
Decimal('123456758365483459347856')
>>> B = A.sqrt()**2
>>> B
Decimal('123456758365483459347856.0000')
>>> A == B
True
>>> int(B)
123456758365483459347856
I use version 3.6, which has no hardcoded limit on the size of integers. I don't know if, in 2.7, casting B as an int would cause overflow, but decimal is incredibly useful regardless.

Heron method in Python

Heron's method generates a sequence of numbers that represent better and better approximations for √n. The first number in the sequence is an arbitrary guess; every other number in the sequence is obtained from the previous number prev using the formula:
(1/2)*(prev+n/prev)
I am supposed to write a function heron() that takes as input two numbers: n and error. The function should start with an initial guess of 1.0 for √n and then repeatedly generate better approximations until the difference (more precisely, the absolute value of the difference) between successive approximations is at most error.
usage:
>>> heron(4.0, 0.5)
2.05
>>> heron(4.0, 0.1)
2.000609756097561
this is a bit tricky, but I will need to keep track of four variables:
# n, error, prev and current
I will also need a while loop with the condition:
((current - prev) > error):
A general rule for the while loop is that:
# old current goes into new prev
So this is what I got so far, it's not much because to start with I don't know how to incorporate the 'if' statement under the while loop.
def heron(n, error):
guess = 1
current = 1
prev = 0
while (current - prev) > error:
previous==1/2*(guess+n/guess):
print (previous) # just a simple print statement
# in order to see what i have so far
Can someone give me a few pointers in the right direction please?
thank you
If you don't want to use generators then the simplest would be:
def heron(n, error):
prev, new = 1.0, 0.5 * (1 + n)
while abs(new - prev) > error:
prev, new = new, 0.5 * (new + n/new)
return new
You can also generate an "infinite" sequence of heron numbers:
def heron(n):
prev = 1.0
yield prev, float('inf')
while True:
new = 0.5 * (prev + n/prev)
error = new - prev
yield new, error
prev = new
Now you can print so many numbers as you like, for example:
list(islice(heron(2), 3)) # First 3 numbers and associated errors
Generate as long as the error is greater than 0.01:
list(takewhile(lambda x:x[1] > 0.01, heron(2)))
Just to build on #elyase's answer, here's how you would get the arbitrary precision square root from the heron number generator they have provided. (the generator just gives the next number in the heron sequence)
def heron(n): ### posted by elyase
a = 1.0
yield a
while True:
a = 0.5 * (a + n/a)
yield a
def sqrt_heron(n, err):
g = heron(n)
prev = g.next()
current = g.next()
while( (prev - current) > err):
prev = current
current = g.next()
print current, prev
return current
print sqrt_heron(169.0,0.1)
Aside from python syntax, the thing that may be messing you up is that you need two guesses calculated from your initial guess to get started, and you compare how far apart these two guesses are. The while condition should be (prev - current) > err not (current - prev) > err since we expect the previous guess to be closer to the square (and therefore larger) than the current guess which should be closer to the square root. Since the initial guess could be any positive number, we need to calculate two iterations from it, to ensure that current will be less than prev.
The other answers up as I write this are using a Python generator function. I love generators but those are overkill for this simple problem. Below, solutions with simple while loops.
Comments below the code. heron0() is what you asked for; heron() is my suggested version.
def heron0(n, error):
guess = 1.0
prev = 0.0
while (guess - prev) > error:
prev = guess
guess = 0.5*(guess+n/guess)
print("DEBUG: New guess: %f" % guess)
return guess
def _close_enough(guess, n, allowed_error):
low = n - allowed_error
high = n + allowed_error
return low <= guess**2 <= high
def heron(n, allowed_error):
guess = 1.0
while not _close_enough(guess, n, allowed_error):
guess = 0.5*(guess+n/guess)
print("DEBUG: New guess: %f" % guess)
return guess
print("Result: %f" % heron0(4, 1e-6))
print("Result: %f" % heron(4, 1e-6))
Comments:
You don't really need both guess and current. You can use guess to hold the current guess.
I don't know why you were asking about putting an if statement in the while loop. In the first place, it is easy: you just put it in, and indent the statement(s) that are under the if. In the second place, this problem doesn't need it.
It's easy and fast to detect whether guess is close to prev. But I think for numerical accuracy, it would be better to directly test how good a square root guess actually is. So, square the value of guess and see if that is close to n. See how in Python it is legal to test whether a value is, at the same time, greater than or equal to a lower value and also less than or equal to a high value. (The alternate way to check: abs(n - guess**2) <= allowed_error)
In Python 2.x, if you divide an integer by an integer you will probably get an integer result. Thus 1/2 can very possibly have a result of 0. There are a couple of ways to fix that, or you can run your program in Python 3.x which guarantees that 1/2 returns 0.5, but it's simple to make your starting value for guess be a floating-point number.
I think this meets your requirements (note: I wrote it with python 2.7.10): it doesn't assume a guess of 1 and it takes takes 'num' and 'tolerance' as arguments for 'n' and 'error'. Also, it doesn't use variables "prev" and "current" or a while loop - are those part of your requirements, or your thoughts regarding a solution?
def heron(num, guess, tolerance):
if guess**2 != num:
##print "guess =", guess
if abs(float(num) - float(guess)**2) > float(tolerance):
avg_guess = 0.5 * (float(guess) + (float(num) / float(guess)))
return heron(num, avg_guess, tolerance)
print "Given your tolerance, this is Heron's best guess:", guess
else:
print guess, "is correct!"
Uncomment the print cmd if you want to see the progression of guesses.
I was dealing with the same problem and not many tools to solve it since my knowledge in Python is very limited.
I came up with this solution that is not very elegant nor advanced, but it solves the problem using Heron's algorithm. Just want it to share it here:
print("Please enter a positive integer 'x' to find its square root.")
x = int(input("x ="))
g = int(input("What's your best guess: "))
results = [g]
if g * g == x:
print("Good guess! The square root of", x, "is", g)
else:
g = (g + (x / g)) / 2
results.append(g)
while results[-1] != results[-2]:
g = (g + (x / g)) / 2
results.append(g)
else:
print(results)
print("Not quite. The square root of", x, "is", results[-1])

Python 3 integer division. How to make math operators consistent with C

I need to port quite a few formulas from C to Python and vice versa. What is the best way to make sure that nothing breaks in the process?
I am primarily worried about automatic int/int = float conversions.
You could use the // operator. It performs an integer division, but it's not quite what you'd expect from C:
A quote from here:
The // operator performs a quirky kind of integer division. When the
result is positive, you can think of
it as truncating (not rounding) to 0
decimal places, but be careful with
that.
When integer-dividing negative numbers, the // operator rounds “up”
to the nearest integer. Mathematically
speaking, it’s rounding “down” since
−6 is less than −5, but it could trip
you up if you were expecting it to
truncate to −5.
For example, -11 // 2 in Python returns -6, where -11 / 2 in C returns -5.
I'd suggest writing and thoroughly unit-testing a custom integer division function that "emulates" C behaviour.
The page I linked above also has a link to PEP 238 which has some interesting background information about division and the changes from Python 2 to 3. There are some suggestions about what to use for integer division, like divmod(x, y)[0] and int(x/y) for positive numbers, perhaps you'll find more useful things there.
In C:
-11/2 = -5
In Python:
-11/2 = -5.5
And also in Python:
-11//2 = -6
To achieve C-like behaviour, write int(-11/2) in Python. This will evaluate to -5.
Some ways to compute integer division with C semantics are as follows:
def div_c0(a, b):
if (a >= 0) != (b >= 0) and a % b:
return a // b + 1
else:
return a // b
def div_c1(a, b):
q, r = a // b, a % b
if (a >= 0) != (b >= 0) and r:
return q + 1
else:
return q
def div_c2(a, b):
q, r = divmod(a, b)
if (a >= 0) != (b >= 0) and r:
return q + 1
else:
return q
def mod_c(a, b):
return (a % b if b >= 0 else a % -b) if a >= 0 else (-(-a % b) if b >= 0 else a % b)
def div_c3(a, b):
r = mod_c(a, b)
return (a - r) // b
With timings:
import itertools
n = 100
l = [x for x in range(-n, n + 1)]
ll = [(a, b) for a, b in itertools.product(l, repeat=2) if b]
funcs = div_c0, div_c1, div_c2, div_c3
for func in funcs:
correct = all(func(a, b) == funcs[0](a, b) for a, b in ll)
print(f"{func.__name__} correct:{correct} ", end="")
%timeit [func(a, b) for a, b in ll]
# div_c0 correct:True 100 loops, best of 5: 10.3 ms per loop
# div_c1 correct:True 100 loops, best of 5: 11.5 ms per loop
# div_c2 correct:True 100 loops, best of 5: 13.2 ms per loop
# div_c3 correct:True 100 loops, best of 5: 15.4 ms per loop
Indicating the first approach to be the fastest.
For implementing C's % using Python, see here.
In the opposite direction:
Since Python 3 divmod (or //) integer division requires the remainder to have the same sign as divisor at non-zero remainder case, it's inconsistent with many other languages (quote from 1.4. Integer Arithmetic).
To have your "C-like" result same as Python, you should compare the remainder result with divisor (suggestion: by xor on sign bits equals to 1, or multiplication with negative result), and in case it's different, add the divisor to the remainder, and subtract 1 from the quotient.
// Python Divmod requires a remainder with the same sign as the divisor for
// a non-zero remainder
// Assuming isPyCompatible is a flag to distinguish C/Python mode
isPyCompatible *= (int)remainder;
if (isPyCompatible)
{
int32_t xorRes = remainder ^ divisor;
int32_t andRes = xorRes & ((int32_t)((uint32_t)1<<31));
if (andRes)
{
remainder += divisor;
quotient -= 1;
}
}
(Credit to Gawarkiewicz M. for pointing this out.)
You will need to know what the formula does, and understand both the C implementation and how to implement it in Python. But unless you are doing integer maths it should be quite similar, and if you are doing integer maths, the question is why. :)
Integer maths are either done because of some specific purpose, often related to computers, or because it's faster than floats when doing massive computations, like Fractint does for fractals, and in that case Python is usually not the right choice. ;)

Resources