同月同日出生人员算法

本文通过JAVA实现了一个计算在一个班级中出现同月同日生的概率算法,并针对大数据量进行了优化,使用BigInteger和BigDecimal避免整数溢出,同时对比了几种不同的阶乘算法。

现在在做数据中心,来了几个新人,因为对于统计什么的没有什么概念,我就想到了大学的时候上概统学到的一个例子,在一个班级有多少个人的时候,出现同月同日生的人的概率会大于 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 实在是太浪费性能了。并且这里阶乘没有使用递归算法,因为使用迭代的话很有可能造成内存溢出,用迭代算法就会好很多。好久没法日志了,这篇就当练手。里面有很多写死的地方,不是很好,仅供参考。



转载于:https://my.oschina.net/sanji/blog/151259

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值