源本科技 | 码上会

质数检测器

2026/01/12
18
0

学习目标

  • 理解质数的数学定义及其在编程中的判断逻辑

  • 掌握基于平方根优化的质数检测算法

  • 学会构建完整的 Web 表单交互应用(HTML + CSS + JS)

  • 实现用户输入验证与动态结果反馈

  • 培养基础算法思维与性能优化意识


什么是质数

质数是指大于 1 且仅能被 1 和自身整除的自然数

✅ 例如:2、3、5、7、11、13
❌ 非质数(合数):4(=2×2)、6(=2×3)、9(=3×3)

注意:1 不是质数,0 和负数也不属于质数范畴


应用功能设计

我们将开发一个质数检测 Web 应用,具备以下功能:

  • 用户在输入框中输入一个整数

  • 点击【检查】按钮后,程序判断该数是否为质数

  • 动态显示结果,并使用颜色区分:

    • 绿色:是质数

    • 🔵 蓝色:是非质数(合数)

    • 红色:输入无效(如 ≤1 或非数字)


HTML 结构搭建

<div class="container">
  <h1>质数检测器</h1>
  <input type="number" id="input" placeholder="请输入一个数字">
  <button onclick="checkPrime()">检查</button>
  <p id="result"></p>
</div>

元素说明:

  • <input type="number">:限制用户只能输入数字

  • id="input":用于 JavaScript 获取用户输入

  • onclick="checkPrime()":点击按钮触发检测函数

  • id="result":用于动态显示判断结果


CSS 样式美化

body {
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background-color: #f4f4f9;
}

.container {
  text-align: center;
  background: white;
  padding: 20px;
  border-radius: 10px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

input {
  padding: 10px;
  width: 200px;
  margin: 10px 0;
  border: 1px solid #ccc;
  border-radius: 5px;
  font-size: 16px;
}

button {
  padding: 10px 20px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
}

button:hover {
  background-color: #45a049;
}

#result {
  margin-top: 20px;
  font-size: 18px;
  min-height: 24px; /* 防止布局跳动 */
}

设计亮点:

  • 页面整体垂直水平居中

  • 卡片式容器 + 阴影,提升视觉层次

  • 按钮悬停效果增强交互体验

  • min-height 避免结果切换时页面“抖动”


JavaScript 核心逻辑

function checkPrime() {
  // 1. 获取并解析用户输入
  const inputStr = document.getElementById('input').value.trim();
  const num = parseInt(inputStr, 10);

  // 2. 获取结果展示元素
  const resultElement = document.getElementById('result');

  // 3. 输入验证
  if (!inputStr || isNaN(num) || num <= 1) {
    resultElement.textContent = "请输入一个大于 1 的整数。";
    resultElement.style.color = "red";
    return;
  }

  // 4. 质数判断(优化版)
  let isPrime = true;
  if (num === 2) {
    isPrime = true; // 2 是唯一的偶质数
  } else if (num % 2 === 0) {
    isPrime = false; // 所有其他偶数都不是质数
  } else {
    // 只需检查奇数因子,从 3 到 √num
    for (let i = 3; i <= Math.sqrt(num); i += 2) {
      if (num % i === 0) {
        isPrime = false;
        break;
      }
    }
  }

  // 5. 显示结果
  if (isPrime) {
    resultElement.textContent = `${num} 是一个质数。`;
    resultElement.style.color = "green";
  } else {
    resultElement.textContent = `${num} 是一个合数。`;
    resultElement.style.color = "blue";
  }
}

完整代码整合

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>质数检测器</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-color: #f4f4f9;
    }
    .container {
      text-align: center;
      background: white;
      padding: 20px;
      border-radius: 10px;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    }
    input {
      padding: 10px;
      width: 200px;
      margin: 10px 0;
      border: 1px solid #ccc;
      border-radius: 5px;
      font-size: 16px;
    }
    button {
      padding: 10px 20px;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-size: 16px;
    }
    button:hover {
      background-color: #45a049;
    }
    #result {
      margin-top: 20px;
      font-size: 18px;
      min-height: 24px;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>质数检测器</h1>
    <input type="number" id="input" placeholder="请输入一个数字">
    <button onclick="checkPrime()">检查</button>
    <p id="result"></p>
  </div>

  <script>
    function checkPrime() {
      const inputStr = document.getElementById('input').value.trim();
      const num = parseInt(inputStr, 10);
      const resultElement = document.getElementById('result');

      if (!inputStr || isNaN(num) || num <= 1) {
        resultElement.textContent = "请输入一个大于 1 的整数。";
        resultElement.style.color = "red";
        return;
      }

      let isPrime = true;
      if (num === 2) {
        isPrime = true;
      } else if (num % 2 === 0) {
        isPrime = false;
      } else {
        for (let i = 3; i <= Math.sqrt(num); i += 2) {
          if (num % i === 0) {
            isPrime = false;
            break;
          }
        }
      }

      if (isPrime) {
        resultElement.textContent = `${num} 是一个质数。`;
        resultElement.style.color = "green";
      } else {
        resultElement.textContent = `${num} 是一个合数。`;
        resultElement.style.color = "blue";
      }
    }
  </script>
</body>
</html>

进阶练习

  1. 支持超大数检测:使用 BigInt 处理超过 Number.MAX_SAFE_INTEGER 的数值

  2. 批量检测:允许用户输入多个数字(如逗号分隔),一次性返回所有结果

  3. 性能计时:显示算法执行耗时,直观感受优化效果

  4. 历史记录:用 localStorage 保存最近 10 次检测结果

  5. 可视化因子:若为合数,列出其最小质因数


重点总结

  • 质数定义:大于 1 且仅有两个正因数(1 和自身)

  • 核心算法:只需检查从 2 到 √n 的整除性

  • 性能优化:跳过偶数、单独处理 2、使用奇数步长

  • 用户体验:清晰的输入提示、颜色反馈、错误处理

  • 工程实践:分离关注点(HTML 结构、CSS 样式、JS 逻辑)


思考题

  1. 为什么我们只需要检查到 Math.sqrt(n) 而不是 n-1?请用数学原理解释。

  2. 如果用户输入 2147483647(一个已知的大质数),当前算法能否高效处理?为什么?

  3. 如何修改代码,使其能正确处理 10、负数和小数?这些情况应如何向用户反馈?