开发者

How can I improve this code?

开发者 https://www.devze.com 2023-01-06 04:15 出处:网络
# max_list = [83, 1350, 1, 100] for i in range(len(max_list)): new_value = 1 while new_value < max_list[i]:
# 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]
0

精彩评论

暂无评论...
验证码 换一张
取 消