I have a list that contains values generated randomly. Each value of that list corresponds to one particular parameter like distance, time and so on.
I have created a function that will round off each value of that list to the number of digits entered by the user:
def round_list(list_x):
for i in range(0, len(list_x)):
incrementer = raw_input('Enter the increment value: ')
list_x[i] = np.round(list_x[i], int(incrementer))
return list_x
x = round_list(x)
print(x)
But this will only work to set the decimal points right?
What if the user wants it to be rounded off to every 0.25 or every 0.03?
How would I incorporate that? I don't think round() can accomplish that.
Rounding to the nearest fractional value (say 0.25) can be done by dividing by the fraction, then rounding to the nearest integer, then multiplying by the fraction.
Something like this:
def roundToBase(num, base):
return np.round(float(num) / base, 0) * base
print(roundToBase(1.3,0.25)) # 1.25
# also works for non-fractional bases,
# eg round to nearest multiple of 5:
print(roundToBase(26,5)) # 25
Try this:
def round(number, nearest):
if ((number % nearest) / nearest) < 0.5:
return (number - (number % nearest))
else:
return ((number - (number % nearest)) + nearest)
Explanation:
The if checks if the the difference between the number and the most previous multiple of nearest is less than half of nearest. If it is, it means that the number needs to be rounded down, which is why, if it's True, it returns the most previous multiple of nearest. If it's False, it returns (the most previous multiple of nearest) + nearest.
Related
I'm having trouble finding the smallest number possible from the following question:
Matchsticks are ideal tools to represent numbers. A common way to represent the ten decimal digits with matchsticks is the following:
This is identical to how numbers are displayed on an ordinary alarm clock. With a given number of matchsticks you can generate a wide range of numbers. We are wondering what the smallest and largest numbers are that can be created by using all your matchsticks.
Input:
On the first line one positive number: the number of testcases, at most 100. After that per testcase:
One line with an integer n (2 <= n <= 100): the number of matchsticks you have.
Output:
Per testcase:
One line with the smallest and largest numbers you can create, separated by a single space. Both numbers should be positive and contain no leading zeroes.
I've tried multiple different ways to try to solve this problem, I'm currently trying to:
find the minimal number of digits needed for the smallest number
send digit to a function minimum() which should generate all the different combinations of numbers that are the length of digits. I want to store all these numbers in a list and then take min() to get the smallest one. I'm not getting this part to work, and would appreciate some inspiration.
Something to remember is that the number can't start with a 0.
if 2 <= n <= 100:
value = (n+6)//7
Unless I'm mistaken, this should work for part 2 (added a fix for 17, 24...):
numdict = {2:1,3:7,4:4,5:2,6:0,7:8,8:10,9:18,10:22,11:20,12:28,13:68}
def min_stick(n):
if 2 <= n <= 13:
return numdict[n]
digits = (n + 6) // 7
base = str(numdict[7+n%7])
if base == '22':
base = '200'
return int(base+"8"*(digits - len(base)))
And, though this one's a no-brainer:
def max_stick(n):
if n%2:
return int("7"+"1"*((n-3)//2))
return int("1"*(n//2))
Ok, so just for the sake of it, I coded what you asked: a recursive function that returns all possible combinations with n matchsticks.
stick = {0:6,1:2,2:5,3:5,4:4,5:5,6:6,7:3,8:7,9:6}
def decompose(n):
retlist = []
if n==0:
return [""]
for i in stick:
if (left := n-stick[i]) >1 or left == 0:
retlist += [str(i)+el for el in decompose(left)]
return retlist
def extr_stick(n):
purged_list = [int(i) for i in decompose(n) if not i.startswith('0')]
return min(purged_list), max(purged_list)
It becomes slow when n grows, but anyway...
extr_stick2(30)
Out[18]: (18888, 111111111111111)
I need to write a code that first calculates an approximation to a logarithm using a series expansion, then display that approximation, as well as the difference between the approximation and the actual logarithm result. The numbers all have to be rounded to 6 decimal places.
The values I am receiving as input are the number which I have to find the logarithm of, and how many terms of the series expansion of the logarithm I want to use.
First, I have to define and call the main function, then initialize any variables, then prompt the user for values, then setup a for-loop to perform the series expansion, then calculate the actual logarithm answer, then calculate the difference. Finally, I have to print the approximation value and the difference. I also need to make sure to include comments for each step.
The formula for a series expansion of a logarithm for a real number x, where 0<x<2, is as follows:
log(x) = (x-1) - (1/2)(x-1)^2 + (1/3)(x-1)^3 - (1/4)(x-1)^4 + ...
The problem I'm having trouble solving is how to use the for loop to alternate the addition and subtraction. I'm also not sure if the rest of my code is written properly, but it's running. The answers I'm getting out of it though are just not the correct math.
Here is the code I have written so far:
# This program displays the approximate logarithm and the difference between that and the actual logarithm of a number inputted by the user to six decimal places.
# The definition of the main function
def main():
import math
# Initialize any necessary variables and prompt the user for values
num = eval(input("Enter the number whose logarithm you want to be computed: "))
term = eval(input("Enter how many terms of the series expansion for logarithms you want to use: "))
approx = 0
# Setup a loop based on the values entered by the user
# Calculate an approximation to the logarithm of the number entered by the user
for i in range(2, term+1):
if i % 2 == 0:
approx += (num-1) - ((1/i)*(num-1)**i)
else:
approx += (num-1) - ((1/i)*(num-1)**i) + ((1/(i+1))*((num-1)**(i+1))
rapprox = round(approx, 6)
# Compute logarithm and difference
mog = math.log(num)
rmog = round(mog, 6)
diffy = rapprox - rmog
# Display the computed values
print("The computed approximation to log", num, "is: ", rapprox)
print("The difference between the approximation and the actual value for log", num, "is: ", diffy)
# Calling the main function
if __name__ == "__main__":
main()
We have been given two sample outputs which look like this:
Please enter the number whose logarithm you want to be computed: 1.5
Please enter how many terms of the series expansion for logarithm you want to use: 5
The computed approximation to log 1.5 is: 0.407292
The difference between the approximation and the actual value for log 1.5 is: 0.001827
and this:
Please enter the number whose logarithm you want to be computed: 0.8
Please enter how many terms of the series expansion for logarithm you want to use: 4
The computed approximation to log 0.8 is: -0.223067
The difference between the approximation and the actual value for log 0.8 is: 0.000077
If you need any more info on the question because it's not clear, I can clarify, thanks!
Note that
log(x) = (x-1) - (1/2)(x-1)^2 + (1/3)(x-1)^3 - (1/4)(x-1)^4 + ...
= -(1-x) - (1/2)(1-x)^2 - (1/3)(1-x)^3 - (1/4)(1-x)^4 - ...
= -( (1-x) + (1/2)(1-x)^2 + (1/3)(1-x)^3 + (1/4)(1-x)^4 + ... )
Therefore you can implement the approximation of the logarithm as
def log_approx(x, N):
"""Computes an approximation of log(x) using N terms"""
s = 0.0
for n in range(1, N+1):
s -= (1-x)**n / n
return s
or shorter
def log_approx(x, N):
"""Computes an approximation of log(x) using N terms"""
return -sum(((1-x)**n / n for n in range(1, N+1)))
I wrote this code and it's alright with positive numbers, but when I tried negative numbers it crashes. Can you give any hints on how to make it work with negative numbers as well? It needs to be recursive, not iterative, and to calculate the sum of the digits of an integer.
def sum_digits(n):
if n != 0:
return (n % 10 + sum_digits(n // 10))
else:
return 0
if __name__=='__main__':
print(sum_digits(123))
Input: 123
Output: 6
On the assumption that the 'sum' of the three digits of a negative number is the same as that of the absolute value of that number, this will work:
def sum_digits(n):
if n < 0:
return sum_digits(-n)
elif n != 0:
return (n % 10 + sum_digits(n // 10))
else:
return 0
That said, your actual problem here is that Python's handling of modulo for a negative number is different than you expect:
>>> -123 % 10
7
Why is that? It's because of the use of trunc() in the division. This page has a good explanation, but the short answer is that when you divide -123 by 10, in order to figure out the remainder, Python truncates in a different direction than you'd expect. (For good, if obscure, reasons.) Thus, in the above, instead of getting the expected 3 you get 7 (which is 10, your modulus, minus 3, the leftover).
Similarly, it's handling of integer division is different:
>>> -123 // 10
-13
>>> 123 // 10
12
This is un-intuitively correct because it is rounding 'down' rather than 'towards zero'. So a -12.3 rounds 'down' to -13.
These reasons are why the easiest solution to your particular problem is to simply take the absolute value prior to doing your actual calculation.
Separate your function into two functions: one, a recursive function that must always be called with a non-negative number, and two, a function that checks its argument can calls the recursive function with an appropriate argument.
def sum_digits(n):
return _recursive_sum_digits(abs(n))
def _recursive_sum_digits(n):
if n != 0:
return (n % 10 + sum_digits(n // 10))
else:
return 0
Since _recursive_sum_digits can assume its argument is non-negative, you can dispense with checking its sign on every recursive call, and guarantee that n // 10 will eventually produce 0.
If you want to just sum the digits that come after the negative sign, remove the sign by taking the absolute value of the number. If you're considering the first digit of the negative number to be a negative digit, then manually add that number in after performing this function on the rest of the digits.
Here is your hint. This is happening because the modulo operator always yields a result with the same sign as its second operand (or zero). Look at these examples:
>>> 13 % 10
3
>>> -13 % 10
7
In your specific case, a solution is to first get the absolute value of the number, and then you can go on with you approach:
def sum_digits(n):
n = abs(n)
if n != 0:
return (n % 10 + sum_digits(n // 10))
else:
return 0
I have a difficult time dealing with floating point numbers, and I find even the built-in decimal class in Python to be pretty confusing at times. As a solution, I wrote a method myself, which simply takes in a value, and a number of digits which should be shown after the floating point, and returns a string in a nice format. It looks like this:
def format_to_decimal_string(value, decimal_places):
"""
# Given the `value` and `decimal_places`, this method returns a string
in the format of a decimal number. Eg: `format_to_decimal_string('99.99', 1)`
returns '99.9', while `format_to_decimal_string('99.99', 0)` return '99'.
# The arguments are validated, to make sure `value` can be turned into
a decimal number, and `decimal_places` is an integer greater than 0.
The `value` is first turned into a string to accomodate for edge-cases,
such as `format_to_decimal_string(99.99, 2)`.
# If `decimal_number` is zero, we return a formatted zero string.
# The start index is calculated, and using that, we append numbers
to the string. Once again, we make sure to add zeroes to the start
and/or the end if needed.
# Finally, we append the minus sign if needed, and return the result.
"""
# Validating arguments
try:
decimal_number = decimal.Decimal(str(value)).as_tuple()
except:
raise ValueError('The value is not a valid decimal number.')
if not isinstance(decimal_places, int):
raise ValueError('The given decimal places is not an integer.')
if not decimal_places >= 0:
raise ValueError('The given decimal places must be greater than or equal to zero.')
# Check if `decimal_number` is zero
if decimal_number == 0:
result = '0'
if not decimal_places == 0:
result += '.'
for i in range(decimal_places):
result += '0'
return result
# Finding the start index
exponent_start_index = len(decimal_number.digits) + decimal_number.exponent
# Appending the first digit
if exponent_start_index == 0:
result = '0'
else:
result = ''
for digit in decimal_number.digits[0:exponent_start_index]:
result += str(digit)
# Appending the exponents
exponent = ''
if not decimal_places == 0:
result += '.'
for digit in decimal_number.digits[exponent_start_index:(decimal_places + exponent_start_index)]:
exponent += str(digit)
# Adding extra zeroes to make the number have a valid precision
if decimal_places > len(exponent):
for i in range(decimal_places - len(exponent)):
exponent += '0'
# Combining the first digit and the exponents
result = result + exponent
# Appending the minus sign if needed
if decimal_number.sign == 1:
if not decimal.Decimal(result) == 0:
result = '-' + result
return result
Pretty self-explanatory. It accounts for zeroes as well, just to make the output look nice. However, one thing I completely forgot about was rounding up the numbers. For example, format_to_decimal_string(19.2189, 3) returns '19.218', when I would like it to return '19.219'. With such a huge method, I feel like there is no easy way to add a fix to this? Should I try re-writing a new method with another angle of solution with the rounding up, or can it be incorporated into this existing method? Thanks.
If you want to use the decimal module for this, you can do:
decimal.Decimal(19.2189).quantize(decimal.Decimal(10) ** -3)
The quantize method will round decimals to the number of decimal places in its argument (so you could pass .001 instead of raising the decimal to -3).
Using round()
You can use round() to accomplish this.
>>> round(19.2189, 3)
19.219
If you want to cast this number as a string:
>>> str(round(19.2189, 3))
'19.219'
Using format()
You can also use format() to accomplish this:
>>> format(19.2189, '.3f')
'19.219'
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am getting a Wrong Answer for my solution to this problem on SPOJ.
The problem asks to calculate the cube root of an integer(which can be upto 150 digits long), and output the answer truncated upto 10 decimal places.
It also asks to calculate the sum of all the digits in the answer modulo 10 as a 'checksum' value.
Here is the exact problem statement:
Your task is to calculate the cube root of a given positive integer.
We can not remember why exactly we need this, but it has something in
common with a princess, a young peasant, kissing and half of a kingdom
(a huge one, we can assure you).
Write a program to solve this crucial task.
Input
The input starts with a line containing a single integer t <= 20, the
number of test cases. t test cases follow.
The next lines consist of large positive integers of up to 150 decimal
digits. Each number is on its own separate line of the input file. The
input file may contain empty lines. Numbers can be preceded or
followed by whitespaces but no line exceeds 255 characters.
Output
For each number in the input file your program should output a line
consisting of two values separated by single space. The second value
is the cube root of the given number, truncated (not rounded!) after
the 10th decimal place. First value is a checksum of all printed
digits of the cube root, calculated as the sum of the printed digits
modulo 10.
Example
Input:
5
1
8
1000
2 33076161
Output:
1 1.0000000000
2 2.0000000000
1 10.0000000000
0 1.2599210498
6 321.0000000000
Here is my solution:
from math import pow
def foo(num):
num_cube_root = pow(num, 1.0 / 3)
# First round upto 11 decimal places
num_cube_root = "%.11f" % (num_cube_root)
# Then remove the last decimal digit
# to achieve a truncation of 10 decimal places
num_cube_root = str(num_cube_root)[0:-1]
num_cube_root_sum = 0
for digit in num_cube_root:
if digit != '.':
num_cube_root_sum += int(digit)
num_cube_root_sum %= 10
return (num_cube_root_sum, num_cube_root)
def main():
# Number of test cases
t = int(input())
while t:
t -= 1
num = input().strip()
# If line empty, ignore
if not num:
t += 1
continue
num = int(num)
ans = foo(num)
print(str(ans[0]) + " " + ans[1])
if __name__ == '__main__':
main()
It is working perfectly for the sample cases: Live demo.
Can anyone tell what is the problem with this solution?
Your solution has two problems, both related to the use of floating-point arithmetic. The first issue is that Python floats only carry roughly 16 significant decimal digits of precision, so as soon as your answer requires more than 16 significant digits or so (so more than 6 digits before the point, and 10 digits after), you've very little hope of getting the correct trailing digits. The second issue is more subtle, and affects even small values of n. That's that your approach of rounding to 11 decimal digits and then dropping the last digit suffers from potential errors due to double rounding. For an example, take n = 33. The cube root of n, to 20 decimal places or so, is:
3.20753432999582648755...
When that's rounded to 11 places after the point, you end up with
3.20753433000
and now dropping the last digit gives 3.2075343300, which isn't what you wanted. The problem is that that round to 11 decimal places can end up affecting digits to the left of the 11th place digit.
So what can you do to fix this? Well, you can avoid floating-point altogether and reduce this to a pure integer problem. We need the cube root of some integer n to 10 decimal places (rounding the last place down). That's equivalent to computing the cube root of 10**30 * n to the nearest integer, again rounding down, then dividing the result by 10**10. So the essential task here is to compute the floor of the cube root of any given integer n. I was unable to find any existing Stack Overflow answers about computing integer cube roots (still less in Python), so I thought it worth showing how to do so in detail.
Computing cube roots of integers turns out to be quite easy (with the help of a tiny bit of mathematics). There are various possible approaches, but one approach that's both efficient and easy to implement is to use a pure-integer version of the Newton-Raphson method. Over the real numbers, Newton's method for solving the equation x**3 = n takes an approximation x to the cube root of n, and iterates to return an improved approximation. The required iteration is:
x_next = (2*x + n/x**2)/3
In the real case, you'd repeat the iteration until you reached some desired tolerance. It turns out that over the integers, essentially the same iteration works, and with the right exit condition it will give us exactly the correct answer (no tolerance required). The iteration in the integer case is:
a_next = (2*a + n//a**2)//3
(Note the uses of the floor division operator // in place of the usual true division operator / above.) Mathematically, a_next is exactly the floor of (2*a + n/a**2)/3.
Here's some code based on this iteration:
def icbrt_v1(n, initial_guess=None):
"""
Given a positive integer n, find the floor of the cube root of n.
Args:
n : positive integer
initial_guess : positive integer, optional. If given, this is an
initial guess for the floor of the cube root. It must be greater
than or equal to floor(cube_root(n)).
Returns:
The floor of the cube root of n, as an integer.
"""
a = initial_guess if initial_guess is not None else n
while True:
d = n//a**2
if a <= d:
return a
a = (2*a + d)//3
And some example uses:
>>> icbrt_v1(100)
4
>>> icbrt_v1(1000000000)
1000
>>> large_int = 31415926535897932384626433
>>> icbrt_v1(large_int**3)
31415926535897932384626433
>>> icbrt_v1(large_int**3-1)
31415926535897932384626432
There are a couple of annoyances and inefficiencies in icbrt_v1 that we'll fix shortly. But first, a brief explanation of why the above code works. Note that we start with an initial guess that's assumed to be greater than or equal to the floor of the cube root. We'll show that this property is a loop invariant: every time we reach the top of the while loop, a is at least floor(cbrt(n)). Furthermore, each iteration produces a value of a strictly smaller than the old one, so our iteration is guaranteed to eventually converge to floor(cbrt(n)). To prove these facts, note that as we enter the while loop, there are two possibilities:
Case 1. a is strictly greater than the cube root of n. Then a > n//a**2, and the code proceeds to the next iteration. Write a_next = (2*a + n//a**2)//3, then we have:
a_next >= floor(cbrt(n)). This follows from the fact that (2*a + n/a**2)/3 is at least the cube root of n, which in turn follows from the AM-GM inequality applied to a, a and n/a**2: the geometric mean of these three quantities is exactly the cube root of n, so the arithmetic mean must be at least the cube root of n. So our loop invariant is preserved for the next iteration.
a_next < a: since we're assuming that a is larger than the cube root, n/a**2 < a, and it follows that (2a + n/a**2) / 3 is smaller than a, and hence that floor((2a + n/a**2) / 3) < a. This guarantees that we make progress towards the solution at each iteration.
Case 2. a is less than or equal to the cube root of n. Then a <= floor(cbrt(n)), but from the loop invariant established above we also know that a >= floor(cbrt(n)). So we're done: a is the value we're after. And the while loop exits at this point, since a <= n // a**2.
There are a couple of issues with the code above. First, starting with an initial guess of n is inefficient: the code will spend its first few iterations (roughly) dividing the current value of a by 3 each time until it gets into the neighborhood of the solution. A better choice for the initial guess (and one that's easily computable in Python) is to use the first power of two that exceeds the cube root of n.
initial_guess = 1 << -(-n.bit_length() // 3)
Even better, if n is small enough to avoid overflow, is to use floating-point arithmetic to provide the initial guess, with something like:
initial_guess = int(round(n ** (1/3.)))
But this brings us to our second issue: the correctness of our algorithm requires that the initial guess is no smaller than the actual integer cube root, and as n gets large we can't guarantee that for the float-based initial_guess above (though for small enough n, we can). Luckily, there's a very simple fix: for any positive integer a, if we perform a single iteration we always end up with a value that's at least floor(cbrt(a)) (using the same AM-GM argument that we used above). So all we have to do is perform at least one iteration before we start testing for convergence.
With that in mind, here's a more efficient version of the above code:
def icbrt(n):
"""
Given a positive integer n, find the floor of the cube root of n.
Args:
n : positive integer
Returns:
The floor of the cube root of n, as an integer.
"""
if n.bit_length() < 1024: # float(n) safe from overflow
a = int(round(n**(1/3.)))
a = (2*a + n//a**2)//3 # Ensure a >= floor(cbrt(n)).
else:
a = 1 << -(-n.bit_length()//3)
while True:
d = n//a**2
if a <= d:
return a
a = (2*a + d)//3
And with icbrt in hand, it's easy to put everything together to compute cube roots to ten decimal places. Here, for simplicity, I output the result as a string, but you could just as easily construct a Decimal instance.
def cbrt_to_ten_places(n):
"""
Compute the cube root of `n`, truncated to ten decimal places.
Returns the answer as a string.
"""
a = icbrt(n * 10**30)
q, r = divmod(a, 10**10)
return "{}.{:010d}".format(q, r)
Example outputs:
>>> cbrt_to_ten_places(2)
'1.2599210498'
>>> cbrt_to_ten_places(8)
'2.0000000000'
>>> cbrt_to_ten_places(31415926535897932384626433)
'315536756.9301821867'
>>> cbrt_to_ten_places(31415926535897932384626433**3)
'31415926535897932384626433.0000000000'
You may try to use the decimal module with a sufficiently large precision value.
EDIT: Thanks to #DSM, I realised that decimal module will not produce very exact cube roots. I suggest that you check whether all digits are 9s and round it to a integer if that is a case.
Also, I now perform the 1/3 division with Decimals as well, because passing the result of 1/3 to Decimal constructor leads to reduced precision.
import decimal
def cbrt(n):
nd = decimal.Decimal(n)
with decimal.localcontext() as ctx:
ctx.prec = 50
i = nd ** (decimal.Decimal(1) / decimal.Decimal(3))
return i
ret = str(cbrt(1233412412430519230351035712112421123121111))
print(ret)
left, right = ret.split('.')
print(left + '.' + ''.join(right[:10]))
Output:
107243119477324.80328931501744819161741924145124146
107243119477324.8032893150
Output of cbrt(10) is:
9.9999999999999999999999999999999999999999999999998