前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

C语言实现非负整数X算术平方根(计算整数的非负整数次幂c语言)

qiguaw 2025-04-01 21:43:56 资源文章 5 ℃ 0 评论

以下是计算非负整数 x 的算术平方根的 C 语言实现代码,包含逐行解析:

#include 

// 计算并返回 x 的算术平方根(整数部分)
int mySqrt(int x) {
    // 处理 x 为 0 或 1 的特殊情况
    if (x < 2) {
        return x;  // 直接返回自身
    }
    
    // 初始化二分查找的左右边界
    int left = 1;    // 最小可能的平方根
    int right = x;   // 最大可能的平方根(实际会快速缩小范围)
    int ans = 0;     // 保存最终结果
    
    // 二分查找核心逻辑
    while (left <= right) {
        // 计算中间值(避免整数溢出)
        int mid = left + (right - left) / 2;
        
        // 将 mid 的平方转为 long long 类型防止溢出
        long long square = (long long)mid * mid;
        
        if (square == x) {
            // 找到精确平方根,直接返回
            return mid;
        } else if (square < x) {
            // 当前 mid 可能是候选,继续向右查找更大的值
            ans = mid;          // 更新候选值
            left = mid + 1;     // 缩小左边界
        } else {
            // mid 的平方太大,缩小右边界
            right = mid - 1;
        }
    }
    
    // 返回最大的满足条件的整数
    return ans;
}

/**************************** 测试代码 ****************************/
int main() {
    // 测试用例1:完全平方数
    printf("sqrt(4) = %d\n", mySqrt(4));       // 输出: 2
    
    // 测试用例2:非完全平方数
    printf("sqrt(8) = %d\n", mySqrt(8));       // 输出: 2
    
    // 测试用例3:边界值1
    printf("sqrt(1) = %d\n", mySqrt(1));       // 输出: 1
    
    // 测试用例4:边界值0
    printf("sqrt(0) = %d\n", mySqrt(0));       // 输出: 0
    
    // 测试用例5:大数值(46339^2 = 2147482921 < 2147395599)
    printf("sqrt(2147395599) = %d\n", mySqrt(2147395599));  // 输出: 46339
    
    return 0;
}

逐行解析

1. 函数签名

int mySqrt(int x)
  • 功能:接收一个非负整数 x,返回其算术平方根的整数部分。

2. 处理特殊情况

if (x < 2) {
    return x;
}
  • 逻辑:当 x 为 0 或 1 时,平方根就是自身。
  • 必要性:避免后续二分查找的冗余计算。

3. 初始化二分查找边界

int left = 1;    // 最小可能的平方根
int right = x;   // 最大可能的平方根(实际会快速缩小范围)
int ans = 0;     // 保存最终结果
  • left:从 1 开始查找(因为 x >= 2 时平方根至少为 1)。
  • right:初始设为 x(虽然实际平方根不可能超过 x/2,但代码仍能正确收敛)。
  • ans:记录当前满足条件的最大候选值。

4. 二分查找核心逻辑

while (left <= right) {
    // 计算中间值(避免整数溢出)
    int mid = left + (right - left) / 2;
    
    // 将 mid 的平方转为 long long 类型防止溢出
    long long square = (long long)mid * mid;
    
    if (square == x) {
        return mid;  // 找到精确平方根
    } else if (square < x) {
        ans = mid;       // 更新候选值
        left = mid + 1;  // 向右查找
    } else {
        right = mid - 1; // 向左查找
    }
}
  • 防溢出技巧
    • mid = left + (right - left) / 2:避免 (left + right) 的潜在溢出。
    • long long square:确保大数平方计算不会溢出。
  • 三种情况处理
  • 精确命中:直接返回 mid。
  • 平方太小:记录候选值 ans,向右缩小范围。
  • 平方太大:向左缩小范围。

5. 返回结果

return ans;
  • 最终结果:循环结束时,ans 保存的是满足 mid^2 <= x 的最大整数。

测试代码解析

// 测试用例1:完全平方数
printf("sqrt(4) = %d\n", mySqrt(4));  // 输出: 2

// 测试用例2:非完全平方数
printf("sqrt(8) = %d\n", mySqrt(8));  // 输出: 2

// 测试用例3:边界值1
printf("sqrt(1) = %d\n", mySqrt(1));  // 输出: 1

// 测试用例4:边界值0
printf("sqrt(0) = %d\n", mySqrt(0));  // 输出: 0

// 测试用例5:大数值验证
printf("sqrt(2147395599) = %d\n", mySqrt(2147395599));  // 输出: 46339
  • 覆盖场景
    • 完全平方数、非完全平方数。
    • 边界值 0 和 1。
    • 接近 INT_MAX 的大数值。

关键特性总结

特性

说明

时间复杂度

O(log n) → 二分查找的高效性

空间复杂度

O(1) → 仅使用固定数量的变量

防溢出设计

使用 long long 存储平方值,避免中间计算溢出

边界条件处理

显式处理 x < 2 的情况

适用范围

所有非负整数(包括 INT_MAX)


扩展讨论

如果需要实现浮点数精度的平方根(例如保留 3 位小数),可以使用 牛顿迭代法(Newton-Raphson Method)。其核心思想是通过迭代逼近真实值,代码示例如下:

double sqrtNewton(double x) {
    if (x < 0 return -1 double guess='x;' double epsilon='1e-7;' while fabsguess guess - x> epsilon) {
        guess = (guess + x / guess) / 2.0;
    }
    return guess;
}

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表