views:

497

answers:

6

hello everyone. Thank you for your help in advance. I am a student in a concepts of programming class. The lab is run by a TA and today in lab he gave us a real simple little program to build. It was one where it would multiply by addition. Anyway, he had us use absolute to avoid breaking the prog with negatives. I whipped it up real quick and then argued with him for 10 minutes that it was bad math. It was, 4 * -5 does not equal 20, it equals -20. He said that he really dosen't care about that and that it would be too hard to make the prog handle the negatives anyway. So my question is how do I go about this.

here is the prog I turned in:

#get user input of numbers as variables

numa, numb = input("please give 2 numbers to multiply seperated with a comma:")

#standing variables
total = 0
count = 0

#output the total
while (count< abs(numb)):
    total = total + numa
    count = count + 1

#testing statements
if (numa, numb <= 0):
    print abs(total)
else:
    print total

I want to do it without absolutes, but every time I input negative numbers I get a big fat goosegg. I know there is some simple way to do it, I just can't find it.

+3  A: 

Too hard? Your TA is... well, the phrase would probably get me banned. Anyways, check to see if numb is negative. If it is then multiply numa by -1 and do numb = abs(numb). Then do the loop.

Ignacio Vazquez-Abrams
Ummm the whole project is about multiplication; should he implement multiplication by -1 by recursion? Perhaps recursion and stacks are too hard for the TA :-)
John Machin
@John: Nah. Just subtract it from 0.
Ignacio Vazquez-Abrams
+2  A: 

Perhaps you would accomplish this with something to the effect of

text = raw_input("please give 2 numbers to multiply separated with a comma:")
split_text = text.split(',')
a = int(split_text[0])
b = int(split_text[1])
# The last three lines could be written: a, b = map(int, text.split(','))
# but you may find the code I used a bit easier to understand for now.

if b > 0:
    num_times = b
else:
    num_times = -b

total = 0
# While loops with counters basically should not be used, so I replaced the loop 
# with a for loop. Using a while loop at all is rare.
for i in xrange(num_times):
    total += a 
    # We do this a times, giving us total == a * abs(b)

if b < 0:
    # If b is negative, adjust the total to reflect this.
    total = -total

print total

or maybe

a * b
Mike Graham
RTQ: multiplication by addition
Peter Coulton
+3  A: 

The abs() in the while condition is needed, since, well, it controls the number of iterations (how would you define a negative number of iterations?). You can correct it by inverting the sign of the result if numb is negative.

So this is the modified version of your code. Note I replaced the while loop with a cleaner for loop.

#get user input of numbers as variables
numa, numb = input("please give 2 numbers to multiply seperated with a comma:")

#standing variables
total = 0

#output the total
for count in range(abs(numb)):
    total += numa

if numb < 0:
    total = -total

print total
slacker
A: 

How about something like that? (Uses no abs() nor mulitiplication)
Notes:

  • the abs() function is only used for the optimization trick. This snippet can either be removed or recoded.
  • the logic is less efficient since we're testing the sign of a and b with each iteration (price to pay to avoid both abs() and multiplication operator)

def multiply_by_addition(a, b):
""" School exercise: multiplies integers a and b, by successive additions.
"""
   if abs(a) > abs(b):
      a, b = b, a     # optimize by reducing number of iterations
   total = 0
   while a != 0:
      if a > 0:
         a -= 1
         total += b
      else:
         a += 1
         total -= b
   return total

multiply_by_addition(2,3)
6
multiply_by_addition(4,3)
12
multiply_by_addition(-4,3)
-12
multiply_by_addition(4,-3)
-12
multiply_by_addition(-4,-3)
12
mjv
You ought to put the `while` loop inside the `if` statement, since the `if` statement evaluates the same every time. Or set a variable `da` to `1` or `-1`, and `dt` to `total` or `-total`, prior to the while loop.
Mike DeSimone
Functions in Python should start with a lowercase letter. If someone sees `FooBar` (outside of an external library with such a naming convention), they will think it is a class.
Mike Graham
@Mike, yes! You are right this would typically be preferable. In the context of this _contrived_ assignment, I opted for a single while approach, because it mirrored the original algorithm and makes the math more self contained. Although doing all our "sign testing" beforehand and having 2 (or 3 or 4) while loops instead would be equivalent, the single while reads more like a single algorithm (psychological, no doubt).
mjv
@Mike, thanks for pointing that out. Actually PEP8 calls for a name like `mul_by_add()` or better yet `multiply_by_addition()`. My bad, I keep switching languages and also a stringent and silly naming convention at work doesn't help :-(
mjv
+1  A: 

Try this on your TA:

# Simulate multiplying two N-bit two's-complement numbers
# into a 2N-bit accumulator
# Use shift-add so that it's O(base_2_log(N)) not O(N)

for numa, numb in ((3, 5), (-3, 5), (3, -5), (-3, -5), (-127, -127)):
    print numa, numb,
    accum = 0
    negate = False
    if numa < 0:
        negate = True
        numa = -numa
    while numa:
        if numa & 1:
            accum += numb
        numa >>= 1
        numb <<= 1
    if negate:
        accum = -accum
    print accum

output:

3 5 15
-3 5 -15
3 -5 -15
-3 -5 15
-127 -127 16129
John Machin
Technically, the sign inversions (`accum = -accum` and the like) as well as the shifts operations (`numb <<= 1`) are multiplications but+1 none the less for a great idea, and concepts which probably fit into the typical things the OP has or will soon cover in class.
mjv
@mjv: It's called negation, not sign inversion ... if the box being simulated doesn't have a NEG instruction, do it by subtraction from zero. Using your reasoning, the `abs()` sprinkled all over some other answers is also multiplication!! If shifting is multiplication, then so is addition e.g. `numa += numa` !!! Shifting is a very primitive hardware operation and is used in the implementation of multiplication.
John Machin
@John Machin. Right you are, on all counts. And indeed once you look at the level of the CPU, this exercise becomes really awkward to put it politely. Glad we could help the OP, I hate it when instructors seem to discourage students to go the extra mile...
mjv
A: 

Thanks everyone, you all helped me learn a lot. This is what I came up with using some of your suggestions

#this is apparently a better way of getting multiple inputs at the same time than the 
#way I was doing it
text = raw_input("please give 2 numbers to multiply separated with a comma:")
split_text = text.split(',')
numa = int(split_text[0])
numb = int(split_text[1])

#standing variables
total = 0

if numb > 0:
    repeat = numb
else:
    repeat = -numb

#for loops work better than while loops and are cheaper
#output the total
for count in range(repeat):
    total += numa


#check to make sure the output is accurate
if numb < 0:
    total = -total


print total

Thanks for all the help everyone.

dman762000
What's the point of the whole if-else clause, if all it does is a simple `repeat = abs(numb)` ?
slacker
Also, if your problem is solved, then please accept one of the answers (maybe even your own).
slacker
without the if else clause the numbers still return with the absolute value, not the true value so without it the prog still returns 4*-5 as 20 instead of -20
dman762000
Actually, without the if-else clause 4*-5 would return 0, as range() with a negative argument returns an empty list. I was not talking about this logic being *unneeded*. i was talking about it *reinventing the wheel*, as those whole 4 lines could be replaced by a single line that reads `repeat = abs(numb)`. Which would be not only shorter, but also clearer.
slacker
Oh, I see now what you are saying. Ok, sorry about that I am just learning. You are right that does work better and it is cleaner and clearer.
dman762000