Newbie help looping/reducing code

L

Lance Hoffmeyer

Hey all,


Can someone help me reduce this code? It sure seems
like there ought to be a way to loop this or combine
things so that there is only 1 or 3 lines to this
instead of 6. I've been scratching my head over this
for a while though I can't come up with anything.
Just as a note, I need even_odd_round left alone because
it is not always used. I just included for clarity.

As always, thanks in advance,

Lance

T2B = even_odd_round(float(str(T2B)))
VS = even_odd_round(float(str(VS)))
SS = even_odd_round(float(str(SS)))
sh.Cells(21,lastcol+1).Value = float(str(T2B))/100
sh.Cells(22,lastcol+1).Value = float(str(VS))/100
sh.Cells(23,lastcol+1).Value = float(str(SS))/100



def even_odd_round(num):
if(round(num,2) + .5 == int(round(num,2)) + 1):
if num > .5:
if(int(num) % 2):
num = round(num,2) + .1 #an odd number
else:
num = round(num,2) - .1 #an even number
else:
num = 1
rounded_num = int(round(num,0))
return rounded_num
 
P

Paul Rubin

Lance Hoffmeyer said:
T2B = even_odd_round(float(str(T2B)))
VS = even_odd_round(float(str(VS)))
SS = even_odd_round(float(str(SS)))
sh.Cells(21,lastcol+1).Value = float(str(T2B))/100
sh.Cells(22,lastcol+1).Value = float(str(VS))/100
sh.Cells(23,lastcol+1).Value = float(str(SS))/100

First of all, I don't understand float(str(VS)) and so forth; if VS is
(say) an integer, you can say float(VS) directly. Second, even_odd_round
is written in a way that it can accept either an int or a float.

So assuming you need to keep those variables around, I'd write the
first three lines of the above as:

T2B = even_odd_round(T2B)
VS = even_odd_round(VS)
SS = even_odd_round(SS)

or you could get fancier and say

T2B, VS, SS = map(even_odd_round, (T2B, VS, SS))

Then you could write the next three lines as a loop:

for i,v in ((21, T2B), (22, VS), (23,SS)):
sh.Cells(i, lastcol+1) = float(v) / 100.0
 
P

Paul Rubin

Lance Hoffmeyer said:
def even_odd_round(num):
if(round(num,2) + .5 == int(round(num,2)) + 1):
if num > .5:
if(int(num) % 2):
num = round(num,2) + .1 #an odd number
else:
num = round(num,2) - .1 #an even number
else:
num = 1
rounded_num = int(round(num,0))
return rounded_num

I would also rewrite this function. It's quite hard to figure out
what it's intended to do. At minimum it should be carefully
documented. I have the impression it's supposed to be something like
the IEEE rounding mode, that rounds floating point numbers to the
nearest integer, rounding to the even neighbor if the fractional
part (sometimes called the mantissa) is close to 0.5.
if(round(num,2) + .5 == int(round(num,2)) + 1):

The above is true if the mantissa is >= 0.495. So you're going to
round 3.495 up to 4, even though it's actually closer to 3. Is that
really what you want? You're rounding based on a printed
representation rather than on the actual number.
if num > .5:

It looks like for display purposes you're trying to avoid displaying
positive numbers as zero if they're slightly below 0.5. However, that
doesn't prevent the round-to-even behavior if the number is slightly
above 0.5. So you get the anomaly that even_odd_round(0.499) = 1,
but even_odd_round(0.501) = 0. My guess is that's not what you wanted
and that it's a bug.
if(int(num) % 2):
num = round(num,2) + .1 #an odd number
else:
num = round(num,2) - .1 #an even number

If the integer part is odd, round upward, else round downward, ok.
So basically you're going to round to the even neighbor if the
mantissa is close to 0.5, otherwise round to the nearest integer.

I notice also that when num is negative, your function rounds to
the odd neighbor (at least sometimes), differing from IEEE rounding.

I think it's clearer to just separate out the integer and fractional
parts and branch on the fractional part directly. I'll ignore the
issue with negative inputs since I'm guessing you only care about
positive ones:

def even_odd_round(num):
assert num >= 0

# separate the number's integer and fractional parts
intpart, fracpart = int(num), num % 1.0

# decide what to do based on the fractional part
if fracpart < 0.495:
return intpart # round downward
elif fracpart > 0.505 or intpart==0:
return intpart+1 # round upward
else:
return intpart + intpart % 2 # round to even
 
C

Cameron Laird

I would also rewrite this function. It's quite hard to figure out
what it's intended to do. At minimum it should be carefully .
.
.
def even_odd_round(num):
assert num >= 0

# separate the number's integer and fractional parts
intpart, fracpart = int(num), num % 1.0

# decide what to do based on the fractional part
if fracpart < 0.495:
return intpart # round downward
elif fracpart > 0.505 or intpart==0:
return intpart+1 # round upward
else:
return intpart + intpart % 2 # round to even


I have even less idea than Paul what the true intent of even_odd_round()
is. I offer, though, the general observation that it's VERY often possible
to do what people want in this sort of regard with a simple use of
formatting--something like

"%.3f" % num

If one comes from C or Java, it can be hard to appreciate immediately how
useful this is. It's also likely to be more robust than anything naively
written "by hand".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top