高斯圆问题计算异常:r=√18时结果不符求排查
高斯圆问题实现错误的根源及修复方案
你的实现核心问题是浮点数精度误差:当传入Math.sqrt(18)这类非整数的平方根时,其平方值无法被JavaScript的64位浮点数精确表示(实际计算结果是≈17.999999999999996而非精确的18),导致Math.floor计算时得到错误的整数,最终求和结果少了1,乘以4后与预期值差4(57 vs 61)。
误差验证
- 正确的
r²=18时,i=2的项是floor(18/9) - floor(18/11) = 2 - 1 = 1 - 而
r²≈17.999999999999996时,该项变为floor(17.999.../9) - floor(17.999.../11) = 1 - 1 = 0,直接导致求和总和少1。
修复方案1:直接传入r²的值(推荐)
避免浮点数平方的精度问题,修改函数接受r的平方值作为参数,而非r本身,同时优化循环提前终止,避免无效计算:
function computeSummationElement(rSquared, i) { return Math.floor(rSquared / (4 * i + 1)) - Math.floor(rSquared / (4 * i + 3)); } function summation(rSquared) { let sum = 0; let i = 0; while (true) { const denom1 = 4 * i + 1; if (denom1 > rSquared) break; const term1 = Math.floor(rSquared / denom1); const denom2 = 4 * i + 3; const term2 = denom2 > rSquared ? 0 : Math.floor(rSquared / denom2); sum += term1 - term2; i++; } return sum; } function pointsWithRSquared(rSquared) { return 1 + 4 * summation(rSquared); } // 测试用例 console.log(` N(4) = ${pointsWithRSquared(16)}`); // 49 console.log(`N(sqrt(17)) = ${pointsWithRSquared(17)}`); // 57 console.log(`N(sqrt(18)) = ${pointsWithRSquared(18)}`); // 61 console.log(`N(sqrt(20)) = ${pointsWithRSquared(20)}`); // 69 console.log(` N(5) = ${pointsWithRSquared(25)}`); // 81
修复方案2:修正浮点数精度(保留传入r的调用方式)
如果需要保留传入r的接口,可以对r的平方值进行精度修正,针对整数平方根的情况取整:
function computeSummationElement(rSquared, i) { return Math.floor(rSquared / (4 * i + 1)) - Math.floor(rSquared / (4 * i + 3)); } function summation(rSquared) { let sum = 0; let i = 0; while (true) { const denom1 = 4 * i + 1; if (denom1 > rSquared) break; const term1 = Math.floor(rSquared / denom1); const denom2 = 4 * i + 3; const term2 = denom2 > rSquared ? 0 : Math.floor(rSquared / denom2); sum += term1 - term2; i++; } return sum; } function points(r) { let rSquared = r * r; // 修正整数平方根的精度误差 const sqrtRSquared = Math.sqrt(rSquared); if (Number.isInteger(sqrtRSquared)) { rSquared = sqrtRSquared * sqrtRSquared; } else { // 通用修正:将接近整数的r²取整 rSquared = Math.round(rSquared); } return 1 + 4 * summation(rSquared); } // 测试用例 console.log(` N(4) = ${points(4)}`); // 49 console.log(`N(sqrt(17)) = ${points(Math.sqrt(17))}`); // 57 console.log(`N(sqrt(18)) = ${points(Math.sqrt(18))}`); // 61 console.log(`N(sqrt(20)) = ${points(Math.sqrt(20))}`); // 69 console.log(` N(5) = ${points(5)}`); // 81
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

