天之道,损有余而补不足;人之道,损不足而益有余

想起大学时看过的一本书《上帝掷骰子吗》,
记得里面一个故事比喻是(懒得找书了,图书馆看的,大致复述一下)

A和B两个赌徒共100个硬币
起初A有50,B也有50
输赢规则:例如,A有80,B有20。则B有80%胜率、A有20%胜率。
谁赢一次就从对方手里取来1个硬币
随着赌局的进行……这样导致两者十分长久地存在下去,不会迅速有人输光

1.天之道,损有余而补不足

老早就想写个程序验证下了,正巧赶上疫情,赋闲在家~
我把胜率归结为手中的硬币数了,每回合赌局出随机数,数在A的硬币数内(A赢了)则A给B一枚硬币(赢的人给输的人)
我做了如下简化:

硬币多的胜率低----->以硬币作为胜率凭据
赢的人胜率更低----->赢的人给输的人一枚硬币

#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;

int abs(int num)//取绝对值
{
    
    
	if (num < 0) num = -1*num;
	return num;
}

int main()
{
    
    
	srand((unsigned int)time(NULL));
	int zeroTOhundred=-1;
	int a=50, b=50;//a=1~50;b=50~100;
	int sum = 0;
	cout << a <<" "<< b << endl;
	for (;;sum++)
	{
    
    
		zeroTOhundred = abs(rand() % 100);//1-100
		cout << "a:" << a << "  b:" << b << "  赌局结果:" << zeroTOhundred << endl;
		//赌局结果在谁的范围内【谁币多算谁赢】
		//结果在b的范围内,a从b取出1个硬币【赢了的输钱减胜率】
		if (zeroTOhundred > a) {
    
    
			a++;
			b--;
		}
		//结果在a的范围内
		else {
    
    
			a--;
			b++;
		}

		if (a == 0 || b == 0) break;//一方输光,赌局结束
	}

	cout << sum << endl;
	return 0;
}

理论上的可能步数是[50,+∞)。
运行上述代码……很难退出循环,a(也代表了另一方是(40,60)范围内)一直在(40,60)范围内。很难到某一方快输光的情况更别提输光了。

2.人之道,损不足而益有余

前几天看到李永乐老师的视频【如何才能摆脱贫穷?穷人和富人有什么差别?【诺贝尔经济学奖解读】】:https://www.bilibili.com/video/av74644387
联系《上帝掷骰子吗》和《道德经》中的这句话,来写这篇博客也是这视频触发的灵感。

在讲到最后给出了个调查结果的曲线,从这个类似逻辑斯蒂曲线的k/2的那个中点向两边趋近
视频中的内容大致就是
穷人刚有一点钱就去消费,没钱消费时就消费不了。
富人消费不会占用他多少财产,很快又可以恢复。
在这里插入图片描述

——我的话总结一下,就是越富有容错性越高

把之前代码的胜负规则颠倒一下(大于号改小于等于号,还有注释改了一下……),就是以下代码:

#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;

int abs(int num)//取绝对值
{
    
    
	if (num < 0) num = -1*num;
	return num;
}

int main()
{
    
    
	srand((unsigned int)time(NULL));
	int zeroTOhundred=-1;
	int a=50, b=50;//a=1~50;b=50~100;
	int sum = 0;
	cout << a <<" "<< b << endl;
	for (;;sum++)
	{
    
    
		zeroTOhundred = abs(rand() % 100);//1-100
		cout << "a:" << a << "  b:" << b << "  赌局结果:" << zeroTOhundred << endl;
		//赌局结果在谁的范围内【谁币多算谁赢】
		//结果在a的范围内,a从b取出1个硬币【赢了的拿钱加胜率】
		if (zeroTOhundred <= a) {
    
    
			a++;
			b--;
		}
		//结果在a的范围内
		else {
    
    
			a--;
			b++;
		}

		if (a == 0 || b == 0) break;//一方输光,赌局结束
	}

	cout << sum << endl;
	return 0;
}

理论上的可能步数是[50,+∞)。
运行上述代码……我试了十几次,主要在90+回合到200-回合范围内,只有2次超过200回合,可见“损不足而益有余”难以长久。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sinat_27382047/article/details/104185040