• 记录:随机数生成的一个bug分析


    开门见山,直接上代码:

    std::wstring arithmetic_expression::natrual_number_or_fraction_generator()
    {
    	static std::default_random_engine e;
    	static std::uniform_int_distribution<unsigned> natural_fraction(0, 1);
    	static std::uniform_int_distribution<unsigned> natural(1, number_range - 1);
    	
    	std::wstring result;
    	if (natural_fraction(e) == 0)
    	{
    		result =  MyFraction(natural(e), 1).to_wstring();
    	}
    	else if (natural_fraction(e) ==  1)
    	{
    		unsigned a = natural(e);
    		unsigned b = natural(e);
    		result =  MyFraction(a, b).to_wstring();
    	}
    	return result;
    }
    

    上述函数源自于一个生成四则运算的小程序,其功能是在产生四则运算的数字时,随机的产生自然数 或者真分数 ,但在测试时出现了奇怪的输出:

    可以看到在箭头位置部分的数值没有正确的生成。

    为了解决这个问题,我将代码改成了如下的形式,增加一个中间变量储存随机数生成器的值。

    std::wstring arithmetic_expression::natrual_number_or_fraction_generator()
    {
    
    	static std::default_random_engine e;
    	static std::uniform_int_distribution<unsigned> natural_fraction(0, 1);
    	static std::uniform_int_distribution<unsigned> natural(1, number_range - 1);
    	
    	std::wstring result;
    	unsigned choice = natural_fraction(e);
    	if (choice == 0)  //改变
    	{
    	result = MyFraction(natural(e), 1).to_wstring();
    	}
    	else if (choice == 1)
    	{
    	unsigned a = natural(e);
    	unsigned b = natural(e);
    	result = MyFraction(a, b).to_wstring();
    	}
    	return result;
    }
    

    经过修改后可以正常的生成表达式了,问题得到了解决,但原因是什么呢?思考了一中午后,终于发现了关键所在:

    • 每次调用随机数分布函数 时,都会生成一个新的随机数,这是它的语法特征;

    • 我建立的0-1分布,只有两种结果,0 或者1;

    • 在第一种写法中,if...else 判断中的条件语句每次都调用了随机数分布函数,那么可能存在如下的情况

      • if (natural_fraction(e) == 0) 时,natural_fraction(e) 的值为1,由于条件判断为假,跳到else if
      • 此时,继续调用natural_fraction(e) ,于是生成了新的随机数, 其值可能为0,这样的话else if (natural_fraction(e) == 1) 也为假,奇怪现象就此产生 ,返回值变成了空值。

      事实是否就是这样的呢?在debug模式下观察出错的调用部分:

    可以看到,与先前推断的一致。至此,终于揭开了这个bug的背后原因,同时也暴露了我对随机数使用的经验缺乏,掉进了这么个里。

    特此记录!

  • 相关阅读:
    【leetcode】Basic Calculator III
    【leetcode】Reorganize String
    【leetcode】Largest Plus Sign
    【leetcode】Reach a Number
    【leetcode】Network Delay Time
    【leetcode】Monotone Increasing Digits
    【leetcode】Submission Details
    【leetcode】Valid Parenthesis String
    【leetcode】Max Area of Island
    New Concept English three(14)
  • 原文地址:https://www.cnblogs.com/mengmz/p/8505167.html
Copyright © 2020-2023  润新知