一道面试题引发的有关随机数的思考(6)

在上一篇文章(http://blog.csdn.net/xzjxylophone/article/details/6853624)中,关于效率的问题进行简单的讨论,

现在我就用C#中委托来实现RandN_2,算法都是一样的。

类RandN_2:

//支持2-49,包括2和49
public class RandN_2 : Rand7Base
{
	//声明委托,返回true表示已经计算完毕
	protected delegate bool GetNextResult(int remain, int ceiling, ref int result);
	private GetNextResult _getNextResult;

	protected int _remain;       //剩余
	protected int _ceiling;      //大于的最小数
	private RandN_2(int maxNum)
	{
		UpdateMaxNum(maxNum);
	}
	public void UpdateMaxNum(int maxNum)
	{
		_maxNum = maxNum;
		_remain = _maxNum % 7;
		decimal chushu = (decimal)_maxNum / 7;
		_ceiling = (int)Math.Ceiling(chushu);
		switch (_ceiling)
		{
			case 1:
				_getNextResult = NextResult1;
				break;
			case 2:
				_getNextResult = NextResult2;
				break;
			case 3:
				_getNextResult = NextResult3;
				break;
			default:
				_getNextResult = NextResult4567;
				break;
		}
	}
	//小于等于7的时候
	protected bool NextResult1(int remain, int ceiling, ref int result)
	{
		if (remain > _remain)
		{
			result = Next();
			return true;
		}
		result = remain;
		return true;
	}
	//8-14的时候
	protected bool NextResult2(int remain, int ceiling, ref int result)
	{
		if (ceiling == 1)
		{
			return false;
		}
		if (ceiling > 4)
		{
			result = remain;
		}
		else
		{
			if (remain > _remain)
			{
				result = Next();
				
			}
			else
			{
				result = remain + 7;
			}
		}
		return true;
	}
	//15-21的时候
	protected bool NextResult3(int remain, int ceiling, ref int result)
	{
		if (ceiling == 1)
		{
			return false;
		}
		//6,7
		if (ceiling > 5)
		{
			result = remain;
		}
		else if (ceiling > 3)//4,5
		{
			result = remain + 7;
		}
		else //2,3
		{
			if (remain > _remain)
			{
				result = Next();
				
			}
			else
			{
				result = remain + 7 * 2;
			}
		}
		return true;
	}
	//22-49的时候
	protected bool NextResult4567(int remain, int ceiling, ref int result)
	{
		if (ceiling > _ceiling)
			return false;

		result = remain + (ceiling - 1) * 7;
		if (ceiling == _ceiling && _remain != 0)
		{
			if (remain > _remain)
			{
				result = Next();
				
			}
		}
		return true;
	}
	public static RandN_2 GetInstance(int maxNum)
	{
		if (rand == null || !(rand is RandN_2))
		{
			rand = new RandN_2(maxNum);
		}
		else if (rand is RandN_2 && rand.MaxNum != maxNum)
		{
			((RandN_2)rand).UpdateMaxNum(maxNum);
		}
		return (RandN_2)rand;
	}

	override public int Next()
	{
		int result = 0;
		int remain = _rand7.Next();
		bool loop = false;
		int ceiling = 0;
		while (!loop)
		{
			ceiling = _rand7.Next();
			loop = _getNextResult(remain, ceiling, ref result);
		}
		return result;
	}
}


添加测试代码:

static void TestRandN_2()
{
	RandN_2 rand = RandN_2.GetInstance(34);
	TestRand(rand);
	rand = RandN_2.GetInstance(35);
	TestRand(rand);
	rand = RandN_2.GetInstance(6);
	TestRand(rand);
}

测试结果如下:

计算Rand34的概率如下
产生1的概率是:0.0293664
产生2的概率是:0.0293180
产生3的概率是:0.0293527
产生4的概率是:0.0293710
产生5的概率是:0.0295124
产生6的概率是:0.0293318
产生7的概率是:0.0293360
产生8的概率是:0.0293739
产生9的概率是:0.0294344
产生10的概率是:0.0293604
产生11的概率是:0.0294201
产生12的概率是:0.0293619
产生13的概率是:0.0293823
产生14的概率是:0.0295176
产生15的概率是:0.0293114
产生16的概率是:0.0294928
产生17的概率是:0.0294471
产生18的概率是:0.0293353
产生19的概率是:0.0293968
产生20的概率是:0.0294575
产生21的概率是:0.0294152
产生22的概率是:0.0294324
产生23的概率是:0.0294275
产生24的概率是:0.0294937
产生25的概率是:0.0293569
产生26的概率是:0.0294170
产生27的概率是:0.0294112
产生28的概率是:0.0294705
产生29的概率是:0.0294017
产生30的概率是:0.0293598
产生31的概率是:0.0294615
产生32的概率是:0.0294824
产生33的概率是:0.0295156
产生34的概率是:0.0294748
耗时: 3.17424430414457 秒
Average:0.0294118;Max:0.0295176;Min:0.0293114
Max:0.0295176, Max-Average:0.0001058, Bits:0.3598400%
Min:0.0293114, Min-Average:-0.0001004, Bits:-0.3412400%
计算Rand35的概率如下
产生1的概率是:0.0285922
产生2的概率是:0.0285493
产生3的概率是:0.0285821
产生4的概率是:0.0285874
产生5的概率是:0.0285950
产生6的概率是:0.0286506
产生7的概率是:0.0284996
产生8的概率是:0.0285676
产生9的概率是:0.0285698
产生10的概率是:0.0285851
产生11的概率是:0.0285485
产生12的概率是:0.0286162
产生13的概率是:0.0286179
产生14的概率是:0.0285686
产生15的概率是:0.0286348
产生16的概率是:0.0286025
产生17的概率是:0.0285430
产生18的概率是:0.0285673
产生19的概率是:0.0284558
产生20的概率是:0.0286432
产生21的概率是:0.0285322
产生22的概率是:0.0285425
产生23的概率是:0.0285563
产生24的概率是:0.0286283
产生25的概率是:0.0285434
产生26的概率是:0.0285640
产生27的概率是:0.0285837
产生28的概率是:0.0285114
产生29的概率是:0.0285032
产生30的概率是:0.0284974
产生31的概率是:0.0285877
产生32的概率是:0.0286038
产生33的概率是:0.0286174
产生34的概率是:0.0285587
产生35的概率是:0.0285935
耗时: 3.20557551823726 秒
Average:0.0285714;Max:0.0286506;Min:0.0284558
Max:0.0286506, Max-Average:0.0000792, Bits:0.2771000%
Min:0.0284558, Min-Average:-0.0001156, Bits:-0.4047000%
计算Rand6的概率如下
产生1的概率是:0.1670055
产生2的概率是:0.1666923
产生3的概率是:0.1664376
产生4的概率是:0.1666388
产生5的概率是:0.1665858
产生6的概率是:0.1666400
耗时: 2.94888697894323 秒
Average:0.1666667;Max:0.1670055;Min:0.1664376
Max:0.1670055, Max-Average:0.0003388, Bits:0.2033000%
Min:0.1664376, Min-Average:-0.0002291, Bits:-0.1374400%

可以看出在计算Rand6的时候,速度快了很多。

现在既然已经解决了49以内的随机数,那么有没有可能用Rand7计算任意的一个随机数了?

答案是肯定的,下一篇文章我们来解决如何去解决任意一个数


当谈到C++中的随机数面试题时,以下是一些常见的问题和答案: 问题1:如何在C++中生成随机数? 答案:在C++中,可以使用标准库中的`<random>`头文件来生成随机数。通常使用以下步骤: - 创建一个随机数引擎对象,如`std::default_random_engine`。 - 选择合适的随机数分布,如均匀分布`std::uniform_int_distribution`或正态分布`std::normal_distribution`。 - 使用随机数引擎和随机数分布来生成随机数。 问题2:如何生成一个范围在[min, max]之间的随机整数? 答案:可以使用`std::uniform_int_distribution`来实现。以下是一个示例代码: ```cpp #include <iostream> #include <random> int main() { int min = 1; int max = 10; std::random_device rd; std::default_random_engine engine(rd()); std::uniform_int_distribution<int> distribution(min, max); int randomNum = distribution(engine); std::cout << "Random number: " << randomNum << std::endl; return 0; } ``` 问题3:如何生成一个范围在[0, 1)之间的随机浮点数? 答案:可以使用`std::uniform_real_distribution`来实现。以下是一个示例代码: ```cpp #include <iostream> #include <random> int main() { std::random_device rd; std::default_random_engine engine(rd()); std::uniform_real_distribution<double> distribution(0.0, 1.0); double randomNum = distribution(engine); std::cout << "Random number: " << randomNum << std::endl; return 0; } ``` 这些是一些常见的C++随机数面试题,希望对你有所帮助!如有更多问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值