如何实现1-100被3整除余数是5的函数调用:数学原理与编程实践

1次阅读
没有评论

共计 2212 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

问题背景与数学原理分析

初看这个问题可能会觉得矛盾:一个数被 3 整除,余数应该是 0、1 或 2,怎么可能余 5?这其实涉及到模运算的数学定义。在数学中,a ≡ b mod m表示 a 和 b 在除以 m 时有相同的余数,但余数并不限于 0 到 m - 1 的范围。例如,11 ≡ 5 mod 3是正确的,因为 11 除以 3 商 3 余 2,5 除以 3 商 1 余 2,两者余数相同。

如何实现 1 -100 被 3 整除余数是 5 的函数调用:数学原理与编程实践

因此,我们需要找的是满足 x ≡ 5 mod 31 ≤ x ≤ 100的整数 x。通过模运算性质可以转化为x = 3k + 5(k 为整数),然后寻找 x 在 1 到 100 之间的解。

常见错误解法示例

很多开发者第一反应可能会写出这样的代码:

def wrong_solution():
    return [x for x in range(1, 101) if x % 3 == 5]  # 永远返回空列表
function wrongSolution() {return Array.from({length: 100}, (_, i) => i + 1).filter(x => x % 3 === 5);
}

这种写法的问题在于 % 运算符在大多数编程语言中返回的是最小非负余数(0 到 m -1),所以 x % 3 的结果永远不会等于 5。

正确的编程实现

Python 版本

def find_numbers():
    """
    找出 1 -100 范围内满足 x ≡ 5 mod 3 的所有整数
    等价于解方程 x = 3k + 5,其中 x 在 [1,100] 范围内
    """
    result = []
    k = -2  # 从 k =- 2 开始,使得 3k+5= -1,下一个 k =- 1 时 x =2
    while True:
        x = 3 * k + 5
        if x > 100:
            break
        if x >= 1:
            result.append(x)
        k += 1
    return result

# 单元测试
def test_find_numbers():
    expected = [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]
    assert find_numbers() == expected
    print("测试通过!")

test_find_numbers()

JavaScript 版本

function findNumbers() {
    /**
     * 找出 1 -100 范围内满足 x ≡ 5 mod 3 的所有整数
     * 等价于解方程 x = 3k + 5,其中 x 在 [1,100] 范围内
     */
    const result = [];
    let k = -2;  // 从 k =- 2 开始

    while (true) {
        const x = 3 * k + 5;
        if (x > 100) break;
        if (x >= 1) result.push(x);
        k++;
    }

    return result;
}

// 单元测试
function testFindNumbers() {const expected = [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98];
    const actual = findNumbers();
    console.assert(JSON.stringify(actual) === JSON.stringify(expected), 
        ` 测试失败!预期:${expected},实际:${actual}`);
    console.log("测试通过!");
}

testFindNumbers();

性能优化建议

  1. 数学优化:可以直接计算 k 的取值范围,避免循环。最小 k 满足 3k+5≥1 ⇒ k≥-4/3 ⇒ k≥-1;最大 k 满足 3k+5≤100 ⇒ k≤95/3 ⇒ k≤31。所以 k 从 - 1 到 31。
def optimized_find_numbers():
    return [3*k +5 for k in range(-1, 32) if 1 <= 3*k +5 <= 100]
  1. 更通用的函数
def find_mod_numbers(mod, remainder, start, end):
    """通用解法:找出 [start,end] 范围内满足 x ≡ remainder mod mod 的所有整数"""
    # 找到第一个 k 使得 mod*k + remainder >= start
    first_k = (start - remainder + mod - 1) // mod  # 向上取整的技巧
    last_k = (end - remainder) // mod               # 向下取整
    return [mod*k + remainder for k in range(first_k, last_k +1)]

实际应用场景讨论

  1. 日历计算:比如计算某个月的所有星期五,可以看作是 ” 日期 ≡ 5 mod 7″ 的问题
  2. 循环队列:确定队列中特定位置的元素
  3. 密码学:某些加密算法涉及模运算的特殊余数

变体问题思考

如果题目改为余数是负数呢?例如找 1 -100 范围内 x ≡ -1 mod 3 的数。根据模运算定义,这等价于 x ≡ 2 mod 3,所以解法类似。

def find_negative_remainder():
    # x ≡ -1 mod 3 等价于 x ≡ 2 mod 3
    return [x for x in range(1, 101) if x % 3 == 2]

数学思维拓展

这种模运算的思维方式可以应用于:

  1. 哈希函数设计:如何均匀分布键值
  2. 随机数生成:线性同余生成器的原理
  3. 算法竞赛问题:如找出满足特定模条件的子序列

通过这个问题,我们学习到:

  • 编程语言中的 % 运算符与数学模运算的差异
  • 如何将数学概念准确转化为代码
  • 边界条件的处理方法
  • 编写通用函数的重要性

希望这个例子能帮助你在遇到类似问题时,从数学本质出发,找到更优雅的解决方案。

正文完
 0
评论(没有评论)