Java中BigDecimal整除判断代码陷入无限循环,求排查建议
问题分析与改进方案
问题根源
你的代码陷入无限循环的核心原因是对“带有50位小数且能被2或3整除”的逻辑理解偏差:
你当前判断的是小数本身是否是2或3的整数倍,但你遍历的数都是形如 m × 10^-50(m从0开始递增)的极小值。要满足m ×10^-50是2的整数倍,需要m = 2×n×10^50(n为正整数),这个m是一个2后面跟着50个0的超大数,从0开始递增到这个值几乎不可能,自然会一直输出"No divisor."。
更合理的题目理解应该是:将50位小数转换为整数(乘以10^50后),这个整数能被2或3整除,这样的小数符合“带有50位小数且能被2/3整除”的要求(因为除以2/3后仍是有限小数,且可以保留50位小数格式)。
改进代码实现
方案1:直接遍历整数转换为50位小数
这是效率最高的方式,直接找能被2或3整除的整数,再转换为50位小数输出:
import java.math.BigDecimal; import java.math.RoundingMode; public class Divisible { public static void main(String[] args) { // 10^50,用于将整数转换为50位小数 BigDecimal decimalScale = new BigDecimal("100000000000000000000000000000000000000000000000000"); int foundCount = 0; long currentInt = 1; while (foundCount < 10) { if (currentInt % 2 == 0 || currentInt % 3 == 0) { // 将整数转换为50位小数,确保格式正确 BigDecimal result = new BigDecimal(currentInt) .divide(decimalScale, 50, RoundingMode.UNNECESSARY); System.out.println(result); foundCount++; } currentInt++; } } }
方案2:修正原遍历逻辑的判断规则
如果你坚持要从极小的50位小数开始遍历,修改isDivisible方法,判断小数对应的整数(乘以10^50后)是否能被2或3整除:
import java.math.BigDecimal; public class Divisible { // 10^50,用于将小数转换为整数 private static final BigDecimal SCALE = new BigDecimal("100000000000000000000000000000000000000000000000000"); public static void main(String[] args) { BigDecimal currentNum = new BigDecimal("0.00000000000000000000000000000000000000000000000001"); BigDecimal increment = new BigDecimal("0.00000000000000000000000000000000000000000000000001"); int foundCount = 0; while (foundCount < 10) { boolean divisibleBy2 = isDivisible(currentNum, 2); boolean divisibleBy3 = isDivisible(currentNum, 3); if (divisibleBy2 || divisibleBy3) { System.out.println(currentNum); foundCount++; } currentNum = currentNum.add(increment); } } private static boolean isDivisible(BigDecimal number, int divisor) { // 将小数转换为整数,再判断是否能被divisor整除 BigDecimal integerValue = number.multiply(SCALE); return integerValue.remainder(new BigDecimal(divisor)).compareTo(BigDecimal.ZERO) == 0; } }
额外说明
原代码中初始值是0.000...000(50个0),这个数其实能被2和3整除,但程序输出一次后会开始遍历后续极小值,而后续值无法满足原判断逻辑,导致无限循环。如果需要包含0,可以在初始化时输出它,再从第一个非零50位小数开始遍历。
内容的提问来源于stack exchange,提问作者Osmium
相关产品推荐
相关产品推荐

