如何使用通用类执行递归方法

发布于 2025-02-13 18:53:12 字数 414 浏览 0 评论 0原文

我有一个具有一个函数的类,可以在不使用Build-In方法的情况下进行乘法。我可以在不使用通用的情况下使我的功能工作,但是我可以在使用通用的同时使它起作用。我的问题是,每次尝试调用它时,我的递归呼叫功能都会给我一个错误。有反馈吗?

我的错误是:线程1:exc_bad_access(代码= 2,地址= 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)
        }
    }
}

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)
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三生殊途 2025-02-20 18:53:12

仅当b是一个非负整数时,您的乘法算法才有效。如果b是负面的,或者包含一个分数,则b == 0永远不会变为真。如果您至少将类型t限制为unignedInteger,则编译器在编译时执行这些限制:

class Math5<T: UnsignedInteger> {

您可以概括以使第一个参数可以是任何addiviveArithmetic仅允许unsignedInteger用于第二个参数。让我们删除并使用免费功能:

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

如果您以B的足够大价值传递,则仍然可以使用堆栈溢出崩溃。由于Swift不能保证消除尾声,因此您还应该更改算法以使用循环而不是递归,如果您想避免堆叠溢出。

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
        rhs -= 1
    }
    return answer
}

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 at least constrain type T to UnsignedInteger, then the compiler enforces 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
        rhs -= 1
    }
    return answer
}
拔了角的鹿 2025-02-20 18:53:12

使函数通用

func multiplier<T: Numeric>(_ a:T, _ b:T) -> T {
 if a == 0 || b == 0 {
  return 0
 }
 return a+multiplier(a,b-1)
}

相同的实现

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文