How can I improve this code?
# max_list = [83, 1350, 1, 100]
for i in range(len(max_list)):
new_value = 1
while new_value < max_list[i]:
new_value *= 10
max_list = new_value
What I'm doing is rounding numbers up to the开发者_如何学Go closest, uhm, zero filled value? I'm not sure what it would be called. But basically, I want 83 -> 100, 1 -> 1, 1350 -> 10000, 100 -> 100. I tried using the round() function but couldn't get it to do what I wanted.
This does it but I thought it could be written in less lines.
I'd do it mathematically:
from math import ceil, log10
int(pow(10, ceil(log10(abs(x or 0.1)))))
def nextPowerOfTen(x):
if x in [0, 1]:
return x
elif x < 1:
return -nextPowerOfTen(abs(x))
else:
return 10**len(str(int(x) - 1))
>>> nextPowerOfTen(83)
100
>>> nextPowerOfTen(1350)
10000
>>> nextPowerOfTen(1)
1
>>> nextPowerOfTen(100)
100
>>> nextPowerOfTen(0)
0
>>> nextPowerOfTen(-1)
-1
>>> nextPowerOfTen(-2)
-10
It does something sensible with negatives, not sure if that is the behaviour you want or not.
i need it to be 1350 / 10000 = 0.135 so it's in the [0, 1] range.
Why didn't you say so initially?
new_val = float("0." + str(old_val))
Unless you need the numbers for something else as well?
>>> x = 12345.678
>>> y = round(x)
>>> round(10 * y, -len(str(y)))
100000
Pseudocode:
div = input != 1 ? power(10,truncate(log10(abs(input))) + 1) : 1;
percent = input/div;
Your original code was close, and more easily read than some terse expression. The problem with your code is a couple of minor errors: initializing new_value
each time in the initial scan, rather than only once; and replacing the max_list
with a calculated scalar while looping over it as a list.
On the final line, you must have intended:
max_list[i] = float(max_list[i]) / new_value
but you dropped the array index, which would replace the list with a single value. On the second iteration of the loop, your Python would give an exception due to the invalid index into a non-list.
Because your code develops greater and greater values of new_value as it progresses, I recommend you not replace the list items during the first scan. Make a second scan once you calculate a final value for new_value:
max_list = [83, 1350, 1, 100]
# Calculate the required "normalizing" power-of-ten
new_value = 1.0
for i in range(len(max_list)):
while new_value < max_list[i]:
new_value *= 10.0
# Convert the values to fractions in [0.0, 1.0]
for i in range(len(max_list)):
max_list[i] = max_list[i] / new_value
print max_list
# "[0.0083000000000000001, 0.13500000000000001, 0.0001, 0.01]"
Notice that I was required to initialize new_value as if it were a floating-point value, in order that it would result in floating-point quotients. There are alternative ways to do this, such as using float(max_list[i])
to retrieve the value for normalizing. The original calculation of new_value
was starting over with each element, so your example would return new_value == 100
because this was based off the final element in the input list, which is 100.
from math import ceil, log10
# works for floats, too.
x = [83, 1350, 1, 100, 12.75]
y = [10**ceil(log10(el)) for el in x]
# alt list-comprehension if integers needed
# y = [int(10**ceil(log10(el))) for el in x]
精彩评论