当前位置: 首页 > news >正文

【Java】再一次踩了整数溢出的坑

【Java】再一次踩了整数溢出的坑

  • 一、起因
    • 原题
      • 示例 1
      • 示例 2
      • 提示
    • 我的代码
    • 提交结果
  • 二、思考
    • 修改后的代码如下
  • 三、知识点
    • 1. `int m = l + ((r - l) / 2)`
      • 解释
    • 2. `if (m < x / m)`
      • 解释
  • 四、结尾

一、起因

我在做【力扣】69.x 的平方根 一题的时候,明明觉得逻辑没问题,可答案就是不对。

原题

给你一个非负整数 x ,计算并返回 x算术平方根
由于返回类型是整数,结果只保留整数部分,小数部分将被舍去
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5

示例 1

输入:x = 4
输出:2

示例 2

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842…, 由于返回类型是整数,小数部分将被舍去。

提示

  • 0 <= x <= 231 - 1

我的代码

class Solution {public int mySqrt(int x) {//处理特殊值 0 和 1if (x == 0) {return 0;}if (x == 1) {return 1;}//二分法查找int l = 1, r = x / 2;while (l <= r) {int m = l + ((r - l) / 2);if (m * m == x) {return m;} else if (m * m < x) {l = m + 1;} else {r = m - 1;}}if (r <= l) {return r;} else {return l;}}
}

提交结果

输入:2147395599
输出:1073697799
预期结果:46339

二、思考

我反复检查代码的逻辑,都没发现问题出现在哪里,直到我看见 别人的题解。
对比代码之后我恍然大悟,明白自己又踩了整数溢出的坑。

修改后的代码如下

class Solution {public int mySqrt(int x) {//处理特殊值 0 和 1if (x == 0) {return 0;}if (x == 1) {return 1;}//二分法查找int l = 1, r = x / 2;while (l <= r) {int m = l + ((r - l) / 2);if (m == x / m) {return m;} else if (m < x / m) {l = m + 1;} else {r = m - 1;}}return r;}
}

三、知识点

1. int m = l + ((r - l) / 2)

int m = l + ((r - l) / 2) 而不是直接写 int m = (l + r) / 2 是为了防止整数溢出

解释

  • 假设我们写的是 int m = (l + r) / 2
    lr 都是非常大的正整数时(接近 Integer.MAX_VALUE,即 2147483647),l + r 可能会超过 int 类型的最大表示范围 (2^31 - 1),这会导致溢出,结果会变成负数,从而导致程序的行为不符合预期。
    如: l = 2000000000r = 2000000000,那么 l + r = 4000000000,这是超过 int 的最大值 2147483647 的,会产生溢出。

  • 假设我们写的是 int m = (l + r) / 2
    r > l 时,r - l 不会溢出,它是一个较小的数,(r - l) / 2 也不会产生太大的值,最终加上 l,依然保持在 int 范围内。

2. if (m < x / m)

m < x / m 而不写 m * m < x 也是为了防止整数溢出

解释

原理同上。
m * m > 2147483647 时会发生整数溢出,结果会变成负数,导致程序的行为不符合预期。

四、结尾

当然,也可以将 m * m < x 改成 (long) m * m < x,这样就不用担心整数溢出了,因为 long 类型的最大值比 int 类型的最大值大得多。

http://www.lryc.cn/news/450058.html

相关文章:

  • Windows开发工具使用技巧大揭秘:让编码效率翻倍的秘籍!
  • CSS外边距
  • C++ set,multiset与map,multimap的基本使用
  • 评估潜力无限:解读自闭症患者的工作能力评估
  • js 实现视频封面截图
  • Hadoop FileSystem Shell 常用操作命令
  • uniapp EChars图表
  • 最新版ingress-nginx-controller安装 使用host主机模式
  • 实习问题(配置文件获取参数)
  • C#测试调用Ghostscript.NET浏览PDF文件
  • MySQL本地安装步骤
  • redisson使用笔记
  • 设计模式之享元(Flyweight)模式
  • 桥接(桥梁)模式
  • 语言模型发展史
  • 【Linux】模拟实现一个shell
  • 云原生数据库 PolarDB
  • MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵
  • elastic Search 初步之向量检索的数据写入及检索查询
  • Tdesign TreeSelect 树形选择 多选
  • Pygame中Sprite实现逃亡游戏5
  • 等保2.0数据库测评之达梦数据库测评
  • 集成mcuboot后测试和验证的方法
  • Vulhub zico 2靶机详解
  • 宠物医院微信小程序源码
  • [教程]Crystal源码下载及编译
  • 【Android 14源码分析】WMS-窗口显示-流程概览与应用端流程分析
  • 双指针---(部分地更新)
  • 【Windows】自定义显示器的分辨率
  • 组播基础-2-IGMP协议