views:

188

answers:

7
# 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 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.

+3  A: 
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.

fmark
Fails on powers of 10.
Ignacio Vazquez-Abrams
Fixed failure on powers of 10
fmark
+1  A: 

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?

Anon.
you probably want to use float(), not int()
Bwmat
i'm using floating points too - i forgot to mention it - so i think i'd have to remove the separator. but that looks like it'll work
iceburn
Doesn't this fail for 1, `1->0.1` should be `1->1`?
Stephen
@Bwmat: Fixed, thanks. @Stephen: Yes, it does. However, [0, 1] is actually kind of a funny range to use - [0, 1) is generally more useful. I'd be interested in seeing how @iceburn intends to use these "normalized" values.
Anon.
@Anon i'll use them with a neural network
iceburn
+1  A: 
>>> x = 12345.678
>>> y = round(x)
>>> round(10 * y, -len(str(y)))
100000
myle
doesn't work for floating points though. i forgot to mention that sorry
iceburn
Edited and Fixed.
myle
A: 

Pseudocode:

div = input != 1 ? power(10,truncate(log10(abs(input))) + 1) : 1;
percent = input/div;
Femaref
+11  A: 

I'd do it mathematically:

from math import ceil, log10
int(pow(10, ceil(log10(abs(x or 0.1)))))
danlei
I'd use `pow(10, ceil(abs(log10(x))))` for the case of negative input.
Femaref
What about zero?
myle
+1, Look at you, bringing intelligence where everyone else brought string processing :) And zero is a trivial special case.
Stephen
.. and don't forget to import `*` (or at least `pow`, `ceil` and `log10`) from `math` ;)
mykhal
`int(pow(10, ceil(log10(abs(x) or 0.1))))` would work better for x < 1
mykhal
Good suggestions, added them to the answer.
danlei
@Stephen: str() version is actually a hair (7-8%) faster than the log10() one
Nas Banov
A: 

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.

Heath Hunnicutt
max_list has the maximum of each column in a file. after changing the values i then divide each element for its respective maximum, eg if the first line in my file is: 10, 10, 20, 30 and my maximums are 10, 100, 100, 1000 i'll have 1, 0.1, 0.2, 0.03 as the new first line. the code i posted only shows one part of what i'm doing, which is taking the maximums and rounding them
iceburn
In that case, the only thing wrong with your original code is the "final line" comment I made. :)
Heath Hunnicutt
A: 
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]
Andrew B.