I've been having trouble trying to round my answer for a problem where I find the area of a regular polygon and then square the perimeter. My final answer should be the area plus the perimeter(squared), rounded to 4 decimal places. My math seems to be correct, however, no matter what numbers I use for inputs, there are only zeros after the decimal. I have included a screen shot of my code and incorrect message from the checker that I use.
import math
def polysum(n, s):
a = ((0.25 * n * s ** 2) / (math.tan(math.pi / 2)))
p = ((n * s) ** 2)
total = a + p
return '%.4f' % round(total)
print polysum(8, 8)
Of course you're only getting zeroes after the decimal point, because you are using the round() function to chop off all digits after the decimal point. If that's not what you want, don't do it. Just do:
return "%.4f" % total
Or possibly:
return round(total, 4)
There are two issues:
Change return '%.4f' % round(total) to return round(total,4) or else you are returning a str round to the nearest integer. It looks like the expected output is a float.
The factor of math.tan(math.pi / 2) is incorrect. This should evaluate to infinity (if not for floating point approximations) and is clearly not what you want. It should be math.tan(math.pi / 2 / n).
import math
def polysum(n, s):
a = (0.25 * n * s ** 2) / (math.tan(math.pi / n))
p = ((n * s) ** 2)
total = a + p
ans = round(total, 4)
return ans
print polysum(8,8)
print polysum(4, 89)
from math import *
def polysum(n, s):
lst = [(0.25 * n * s **2) / tan(pi / n), ((n * s) ** 2)]
return round(sum(lst), 4)
I have tried both the test cases. The output is matching.
Related
This is from an assignment I got. I've been trying to find answers on google but nothing helps at all. So far I've done this. I'll appreciate any help!
x = int(input("Enter a value: "))
calculation = sqrt(0.08(x**2 - 8)) + 12 / x + 4
print (calculation)
You are very close. A couple of minor points - to multiply you always need the * operator - 0.08(...) doesn't multiply the value in the brackets by 0.08. Also, you forgot the brackets in a couple of places, e.g. around x + 4.
So this should work:
from math import sqrt
x = int(input("Enter a value: "))
calculation = (sqrt(0.08*(x**2 - 8)) + 12) / (x + 4)
print (calculation)
sqrt is from math library. Import it or you can use **0.5
Method 1
calculation = ((0.08*(x**2 - 8))**0.5 + 12) / (x + 4)
Method 2
Importing math
calculation = (math.sqrt(0.08*(x**2 - 8)) + 12) / (x + 4)
We have a partially working code and 2 examples with different types of custom steps. The example 2 (Int) is working, while the example 1 is not, as it is rounding up instead of down.
import math
def step_size_to_precision(ss):
return ss.find('1') - 1
def format_value(val, step_size_str):
precision = step_size_to_precision(step_size_str)
if precision > 0:
return "{:0.0{}f}".format(val, precision)
return math.floor(int(val))
###########################
# # example 1
step_size = "0.00000100"
quantity = 0.00725562
print(quantity)
print(format_value(quantity, step_size))
# 0.00725562
# 0.007256 <= Is rounding up instead of down. Should be 0.007255
###########################
# # example 2
# step_size = "1"
# quantity = 3.00725562
# print(quantity)
# print(format_value(quantity, step_size))
# returns 3 <= This is correct
###########################
How do we fix it?
You'll want to use Decimal objects to for precise decimal numbers to begin with.
Then, use Decimal.quantize() in the ROUND_DOWN mode.
from decimal import Decimal, ROUND_DOWN
quantity = 0.00725562
step_size = Decimal("0.000001")
print(Decimal(quantity).quantize(step_size, ROUND_DOWN))
prints out
0.007255
Another approach is outlined in this SO answer:
If you want to round down always (instead of rounding to the nearest
precision), then do so, explicitly, with the math.floor()
function:
from math import floor
def floored_percentage(val, digits):
val *= 10 ** (digits + 2)
return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)
print floored_percentage(0.995, 1)
Demo:
>>> from math import floor
>>> def floored_percentage(val, digits):
... val *= 10 ** (digits + 2)
... return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)
...
>>> floored_percentage(0.995, 1)
'99.5%'
>>> floored_percentage(0.995, 2)
'99.50%'
>>> floored_percentage(0.99987, 2)
'99.98%'
For your example:
import math
def step_size_to_precision(ss):
return max(ss.find('1'), 1) - 1
def format_value(val, step_size):
digits = step_size_to_precision(step_size)
val *= 10 ** digits
return '{1:.{0}f}'.format(digits, math.floor(val) / 10 ** digits)
step_size = "0.00000100"
quantity = 0.00725562
print(quantity)
print(format_value(quantity, step_size))
# prints out: 0.007255
A more general approach which allows to round down for step_size which is not only power of 10:
from decimal import Decimal
def floor_step_size(quantity, step_size):
step_size_dec = Decimal(str(step_size))
return float(int(Decimal(str(quantity)) / step_size_dec) * step_size_dec)
Usage:
>>> floor_step_size(0.00725562, "0.00000100")
0.007255
>>> floor_step_size(3.00725562, "1")
3.0
>>> floor_step_size(2.6, "0.25")
2.5
>>> floor_step_size(0.9, "0.2")
0.8
So, I'm trying to find the value of cos(x), where x=1.2. I feel the script I have written should be fine, however, the value I get out isn't correct. That is; cos(1.2)=0.6988057880877979, for 25 terms, when I should get out: cos(1.2)=0.36235775.
I have created a similar program for calculating sin(1.2) which works fine.
Calculating sin(1.2):
import math as m
x=1.2
k=1
N=25
s=x
sign=1.0
while k<N:
sign=-sign
k=k+2
term=sign*x**k/m.factorial(k)
s=s+term
print('sin(%g) = %g (approximation with %d terms)' % (x,s,N))
Now trying to calculate cos(1.2):
import math as m
x=1.2
k=1
N=25
s=x
sign=1.0
while k<N:
sign=-sign
k=k+1
term=sign*x**k/m.factorial(k)
s=s+term
print(s)
You shouldn't be setting your initial sum to 1.2, and your representation of the expansion
is a bit off - we need to account for the even-ness of the function, so increment k by 2. Also, without modifying your program structure, you'd have to set the initial variables so they are correctly put to their starting values at the beginning of the first loop. Re-ordering your loop control flow a bit, we have
import math as m
x=1.2
k=0
N=25
s=0
sign=1.0
while k<N:
term=sign*x**(k)/m.factorial(k)
s=s+term
k += 2
sign = -sign
print(s)
Gives
0.3623577544766735
I think you're using the wrong series for the cosine, the correct formula would be (I highlighted the important differences with ^):
sum_over_n [(-1)**n * x ** (2 * n) / (math.factorial(2 * n))]
# ^^^^ ^^^^
that means to add n-terms you have something like:
def cosine_by_series(x, terms):
cos = 0
for n in range(terms):
cos += ((-1)**n) * (x ** (2*n)) / (math.factorial(2 * n))
return cos
# or simply:
# return sum(((-1)**n) * (x ** (2*n)) / (math.factorial(2 * n)) for n in range(terms)
which gives:
>>> cosine_by_series(1.2, 30)
0.3623577544766735
I really don't know how to write this correctly. This is how I tried:
def is_cardano_triplet(a, b, c):
f = lambda x: x ** 1. / 2
g = lambda x: x ** 1. / 3
return g(a + b*f(c)) + g(a - b*f(c)) == 1
print is_cardano_triplet(2,1,5) # I should get True
I should get True for 2, 1, 5, but I'm not. What's wrong with my function?
Doing a few calculations, I found out that:
and therefore:
Now, due to floating point arithmetic being imprecise on binary-based systems for known reasons, the first formula is pretty hard to compute precisely. However, the second one is much easier to compute without floating point precision errors since that it doesn't involve irrational functions and a, b and c are integers.
Here's the smart solution:
def is_cardano_triplet(a, b, c):
return (a + 1)**2 * (8*a - 1) - 27*b**2*c == 0
>>> is_cardano_triplet(2, 1, 5)
True
The power operator (**) has a higher priority than the division one (/). So you need to set parentheses:
f = lambda x: x ** (1./3)
Still, floating point operations are not exact, so you have to compare with some small uncertainty:
def is_cardano_triplet(a, b, c):
f = lambda x: x ** (1. / 2)
g = lambda x: x ** (1. / 3)
return abs(g(a + b*f(c)) + g(a - b*f(c)) - 1) < 1e-10
Now you get the problem, that negative numbers are only allowed for roots of odd numbers, but floating points aren't exact, so you have to handle negative numbers by hand:
def is_cardano_triplet(a, b, c):
f = lambda x: x ** (1. / 2)
g = lambda x: (-1 if x<0 else 1) * abs(x) ** (1. / 3)
return abs(g(a + b*f(c)) + g(a - b*f(c)) - 1) < 1e-10
Now
print is_cardano_triplet(2,1,5)
results in True.
I have this portion of a class that takes a whole number and a fraction and add them together.
def __add__(self, g):
whole_add=self.whole_number + g.whole_number
numerator = (self.fraction.numerator * g.fraction.denominator ) + (g.fraction.numerator * self.fraction.denominator)
denominator = self.fraction.denominator * g.fraction.denominator
f=Fraction(numerator,denominator)
return '{} and {}'.format(whole_add,f)
fraction_1 = Fraction(3, 4)
fraction_2 = Fraction(2, 3)
mixed_num_1 = MixedNumber(2, fraction_1)
mixed_num_2 = MixedNumber(1, fraction_2)
print(mixed_num_1 + mixed_num_2)
The outcome of this is 3 and 17/12, when it should be 4 and 5/12, I am not sure how to do this, I assume with an if the fraction is >= 1. Any help would be much appreciated
If you are using the fractions library, ou can just sum everything, then take the int() portion of the fraction:
def __add__(self, g):
summed = sum((self.whole_number, g.whole_number, self.fraction, g.fraction))
whole = int(summed)
remainder = summed - whole
return '{} and {}'.format(whole, remainder)
The Fraction() class implements __add__ for you, you can just sum up integers and Fraction() objects and it all works as it should.
Demo using constants:
>>> from fractions import Fraction
>>> summed = sum((2, 1, Fraction(3, 4), Fraction(2, 3)))
>>> whole = int(summed)
>>> remainder = summed - whole
>>> '{} and {}'.format(whole, remainder)
'4 and 5/12'
One little-known but handy factoid is that Python the int() type has both .numerator and .denominator attributes, that the fractions.Fraction() class makes use of. If you are not using the fractions library, you can make use of that yourself:
def __add__(self, g):
summed = 0
for v in (self.whole_number, g.whole_number, self.fraction, g.fraction):
summed = Fraction(summed.numerator * v.denominator +
v.numerator * summed.denominator,
summed.denominator * v.denominator)
whole = summed._numerator // summed._denominator
remainder = Fraction(summed.numerator * whole.denominator -
whole.numerator * summed.denominator,
summed.denominator * whole.denominator)
return '{} and {}'.format(whole, remainder)
One way to "fix" your version would be to deal with the improper fraction directly:
whole_add=self.whole_number + g.whole_number
numerator = (self.fraction.numerator * g.fraction.denominator ) + (g.fraction.numerator * self.fraction.denominator)
denominator = self.fraction.denominator * g.fraction.denominator
whole_add += numerator // denominator
numerator -= numerator % denominator
f=Fraction(numerator,denominator)
return '{} and {}'.format(whole_add,f)
Although there are more efficient ways of doing this addition more directly.