自然对数公式输出异常求助:程序无法生成正确结果
-12*ln(1-x)计算的输出问题 嘿,我来帮你揪出这个问题的根源!你现在是想用线性同余生成器(LCG)生成随机数,再代入-12*ln(1-x)算出前500个结果,但输出始终不对对吧?咱们一步步来拆解可能的问题:
1. 最可能的坑:随机数的区间转换错误
你的LCG公式x(i+1) = (a * x(i) + c) mod k里,k=8192,所以生成的整数x的范围是0到8191。但公式里的x需要是[0,1)区间的double值,如果你直接把int类型的x转成double代入,那1-x会变成负数(比如x=1000时,1-x=-999),而ln(负数)会返回NaN,这肯定会导致输出异常!
正确的转换方式是把整数x除以k,得到(double)x / k,这样结果就落在[0,1)区间里,1-x就会是(0,1],ln计算就正常了。
2. 构造函数的种子初始化问题
你的构造函数代码没写完,但LCG必须要有一个初始的种子值x。如果x没有初始化,或者初始值不合理,生成的随机序列会完全不符合预期。建议用动态种子(比如当前时间)或者固定种子(方便调试)来初始化x,比如:
public myRnd() { // 用当前时间戳取模k作为初始种子,每次运行生成不同序列 this.x = (int) System.currentTimeMillis() % k; // 如果需要固定序列用于调试,可以写死:this.x = 123; }
3. next()方法的实现缺失
你提到了double类型的next()方法,但现有代码里没有这个方法的实现。正确的next()应该先更新LCG的x值,再转换为[0,1)的double,示例如下:
public double next() { // 先计算下一个LCG值 x = (a * x + c) % k; // 转换为[0,1)区间的double return (double) x / k; }
4. 公式计算的细节确认
Java里的Math.log()是自然对数(ln),正好符合你的公式需求,不要误用到Math.log10()(常用对数)。另外,因为我们转换后的x∈[0,1),所以1-x∈(0,1],不会出现ln(0)的情况(x最大是8191,1-x=1/8192≈0.000122,ln这个值是合法的)。
完整可运行的示例代码
把这些修正点整合后,完整代码如下:
public class myRnd { // Linear values for x(i+1) = (a * x(i) + c) % k final static int a = 7893; final static int c = 3517; final static int k = 8192; // Current value for returning int x; public myRnd() { // 初始化种子,这里用当前时间戳取模k this.x = (int) System.currentTimeMillis() % k; } // 生成[0,1)区间的double随机数 public double next() { x = (a * x + c) % k; return (double) x / k; } } // 测试类 public class FormulaCalculator { public static void main(String[] args) { myRnd rndGenerator = new myRnd(); for (int i = 0; i < 500; i++) { double x = rndGenerator.next(); double result = -12 * Math.log(1 - x); System.out.printf("第%d个结果:%.4f%n", i+1, result); } } }
内容的提问来源于stack exchange,提问作者Anna

