




Python Programming Language









Newbie help looping/reducing code
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
Lance Hoffmeyer <l @augustmail.com> writes: > 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
Lance Hoffmeyer <l @augustmail.com> writes: > 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 roundtoeven 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
In article <7x1wkl8xb7.@ruckus.brouhaha.com>, Paul Rubin <http://phr@NOSPAM.invalid> wrote: >Lance Hoffmeyer <l @augustmail.com> writes: >> 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
. . . >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 formattingsomething 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".





