I have a class that has one function that does multiplication without using build-in methods. I got my function to work without using a generic, but I can get it to work while using a generic. My problem is my recursive call-back function is giving me an error each time I try and call it. Any feedback?
my error is : Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ff7bc42af70)
class Math5<T: Numeric> {
func multiplier(_ a: T, _ b: T) -> T {
if a == 0 || b == 0 {
return 0;
} else {
return a multiplier(a, b - 1)
}
}
}
CodePudding user response:
Your multiplication algorithm is only valid if b
is a non-negative integer. If b
is negative, or includes a fraction, then b == 0
will never become true. If you should at least constrain type T
to UnsignedInteger
, thin the compiler will enforce those limitations at compile-time:
class Math5<T: UnsignedInteger> {
You can generalize so that the first argument can be any AdditiveArithmetic
while only allowing an UnsignedInteger
for the second argument. Let's drop the class
and use a free function:
func multiply<LHS: AdditiveArithmetic, RHS: UnsignedInteger>(
_ lhs: LHS,
_ rhs: RHS
) -> LHS {
guard lhs != .zero && rhs != 0 else { return .zero }
return lhs multiply(lhs, rhs - 1)
}
multiply(2.5, 3 as UInt) // result: 7.5
You can still crash with a stack overflow if you pass in a large enough value for b
. Since Swift doesn't guarantee tail call elimination, you should also change your algorithm to use a loop instead of recursion if you want to avoid stack overflows.
func multiply<LHS: AdditiveArithmetic, RHS: UnsignedInteger>(
_ lhs: LHS,
_ rhs: RHS
) -> LHS {
guard lhs != .zero else { return .zero }
var answer: LHS = .zero
var rhs = rhs
while rhs > 0 {
answer = lhs
}
return answer
}
CodePudding user response:
Make the function generic
func multiplier<T: Numeric>(_ a:T, _ b:T) -> T {
if a == 0 || b == 0 {
return 0
}
return a multiplier(a,b-1)
}
Same implementation