使用Math.sqrt计算圆内随机坐标时y值异常的问题排查
圆内随机坐标生成的问题排查与解决
问题背景
我需要生成100个圆心在(0,0)、半径为10的圆内随机坐标,采用y = Math.sqrt(100 - x²)的逻辑计算y的取值范围,但部分y值出现偏大异常,怀疑是double类型的Math.sqrt计算导致问题。试过三角函数实现方式,但想弄清当前计算逻辑出错的原因,是否因小数位数过多导致?该如何解决?
相关代码
主程序代码
package RKap14; import ZindansMethods.ZindanRandom; public class Dot { public double x; public double y; public static void main(String[] arg)throws Exception { //Create the array with null fields? Coord[] c; //Decide how many fields c = new Coord[100]; //Create an object of class Coord in each slot of the array for(int i = 0; i<c.length; i++) { c[i] = new Coord(); } //Assign random coordinates for each field x & y for(int i = 0; i<c.length; i++) { c[i].x = ZindanRandom.randomized(-10,10); //Since sometimes Java calculates wrong and gives numbers above 10 and below -10... while(c[i].x > 10 || c[i].x < -10) c[i].x = ZindanRandom.randomized(-10,10); c[i].y = ZindanRandom.randomized(-Math.sqrt(100-c[i].x*c[i].x), Math.sqrt(100-c[i].x*c[i].x)); } //Print out the coordinates in form: (x,y),(x1,y1)...(x99,y99) for (int i = 0; i<c.length; i++) { System.out.print("(" + c[i].x + "," + c[i].y + ")" + ","); } } } class Coord { double x; double y; }
自定义随机数方法
//Gives random number a to b. For example -10 <= x <= 10 public static double randomized (double a, double b) { return (a-1+Math.random()*Math.abs(b-a+1)+1); }
错误原因分析
问题根本不是Math.sqrt的精度问题,而是你自定义的randomized方法逻辑错误,导致生成的随机数超出预期范围:
- 化简你的
randomized方法返回公式:
等价于:return (a-1 + Math.random()*Math.abs(b-a+1) +1);return a + Math.random() * Math.abs(b - a + 1); - 当你传入
a=-10, b=10时,生成的x范围是[-10, -10 + (10 - (-10) +1))即[-10, 11),这就是你需要加while循环修正x的原因; - 计算y时,传入的范围是
[-s, s](其中s=Math.sqrt(100-x²)),但方法实际生成的y范围是[-s, -s + (s - (-s) +1))即[-s, s+1),这直接导致y可能大于s,进而出现x² + y² > 100的异常情况。
解决方案
修正randomized方法,使其正确生成[a, b)范围内的随机double值(对于连续数值来说,是否包含b的边界没有实际影响):
public static double randomized(double a, double b) { // Math.random() 返回 [0.0, 1.0) return a + Math.random() * (b - a); }
同时可以去掉主程序中修正x的while循环,因为修正后的方法不会生成超出[-10,10)范围的x值。
验证逻辑
生成坐标后,可添加验证代码确保所有点都在圆内:
for (int i = 0; i<c.length; i++) { double distanceSquared = c[i].x * c[i].x + c[i].y * c[i].y; if (distanceSquared > 100.0001) { // 允许极小的浮点误差 System.out.println("超出范围的点:(" + c[i].x + "," + c[i].y + ")"); } }
内容的提问来源于stack exchange,提问作者owns good
相关产品推荐
相关产品推荐

