现在在做数据中心,来了几个新人,因为对于统计什么的没有什么概念,我就想到了大学的时候上概统学到的一个例子,在一个班级有多少个人的时候,出现同月同日生的人的概率会大于 90% 。于是我就用这道问题去考几个来的新人,无一例外都被考蒙掉了,基本说的人数都在 100+ 。所以我就用 JAVA 写了代码来验证结果,顺便回味了下编码的快乐。下面贴出代码
package com.probabilityandstatistic;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
********************************************************************************************
* @ClassName: SameDayRate
* @Description: 同月同日出生人员算法,因为数值太大所以采用普通的数据类型无法计算,特采用 BIGINTEGER 和 BIGDECIMAL
* @author ZhouQian zhouqian@cnsesan.com
* @date 2013-8-8-上午11:01:39
********************************************************************************************
*/
public class SameDayRate {
/**
* @param args
*/
public static void main(String[] args) {
BigInteger start = new BigInteger("30") ;
BigInteger end = new BigInteger("50") ;
for( BigInteger i = start ; i.compareTo(end) == -1 ; i = i.add(BigInteger.ONE) ){
System.out.println("当人数为" + i + "时,出现同月同日生的概率是" + samebornRate(i).floatValue()+ "%" );
}
}
// 有两个人的话,也就是 365*364/365*365
private static BigDecimal samebornRate(BigInteger peopleNum) {
BigInteger max = new BigInteger("366");
BigInteger min = new BigInteger("365");
BigDecimal divide = new BigDecimal(factorial(max.subtract(peopleNum), min));
BigDecimal divided = new BigDecimal(Math.pow(365,peopleNum.floatValue()));
return BigDecimal.ONE.subtract(divide.divide(divided, 6, BigDecimal.ROUND_HALF_DOWN)).multiply(new BigDecimal("100"));
}
// 基本 int 迭代算法
private static float factorial(int start, int end) {
if (end > start && start >= 1) {
int result = 1;
for (int i = start; i <= end; i++) {
result = result * i;
}
return result;
} else {
return -1;
}
}
// big integer 优化迭代算法,传入最小值和最大值进行迭代
public static BigInteger factorial(BigInteger start , BigInteger end) {
if (end.compareTo(start) == 1 && start.compareTo(BigInteger.ONE) == 1) {
BigInteger fact = BigInteger.ONE;
for(BigInteger i = start; i.compareTo(end) <1 ; i = i
.add(BigInteger.ONE)) {
fact = fact.multiply(i);
}
return fact;
} else {
return BigInteger.ZERO;
}
}
// big integer 迭代算法,迭代也就是使用循环运算,递归是采用结果递归的方式
public static BigInteger factorial(BigInteger bigInteger) {
BigInteger fact = BigInteger.ONE;
for (BigInteger i = BigInteger.ONE; i.compareTo(bigInteger) <= 0; i = i
.add(BigInteger.ONE))
fact = fact.multiply(i);
return fact;
}
}
这里把阶乘算法优化了一下,否则计算阶乘要算到 1 实在是太浪费性能了。并且这里阶乘没有使用递归算法,因为使用迭代的话很有可能造成内存溢出,用迭代算法就会好很多。好久没法日志了,这篇就当练手。里面有很多写死的地方,不是很好,仅供参考。