4月15日到17日学习心得二

17.4

随机数

  注意计算机程序中给出的都是伪随机数。c++中不再像C一样使用rand()而是引擎+分布。

default_random_engine e;
for(size_t i=00;i<10;++i)
cout<<e()<<endl;

标准库中其实有多个引擎,最常用的就是default_random_engine.其常用操作有:

e.seed();//指定种子

e.min();

e.max();//该引擎可生产的最大最小值

e.discard(u);//将引擎推进n步

default_random_engine e;
uniform_int_distribution<unsigned> u(0,9);//该分布产生0-9的unsigned
for(size_t i=0;i<10;++i)
cout<<u(e);//u接受的是一个engine而不是engine产生的数

分布对象使用它的引擎参数生成随机数,并将其映射到指定的分布。

当我们说随机数发生器时,是指分布对象和引擎的组合。

vector<unsigned> bad_randVec()
{
	
default_random_engine e(time(0));

default_random_engine e(time(0));

uniform_int_distribution<unsigned> u(0, 9);vector<unsigned> ret;for (size_t i = 0; i < 100; ++i){ret.push_back(u(e));}return ret;}//每次生成相同的结果vector<unsigned> good_randVec(){static default_random_engine e;static uniform_int_distribution<unsigned> u;vector<unsigned> ret;for (size_t i = 0; i < 100; ++i){ret.push_back(u(e));}return ret;}

  因为每次调用bad是都初始化生成engine,seed相同。导致每次的engine和distribution都相同,而下面的使用了static每次的engine和u已经初始化过,seed每调用一次默认改变。

一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为static的,否则每次调用函数都会生成相同的序列。

  随机数发生器通过变换种子来获取不同的随机数,一个很好的方式是使用time()作为种子。

default_random_engine e(time(0));

但注意,如果程序作为某个自动过程的一部分反复运行,将time的作为返回值作为种子的方式就无效了;它可能多次使用的都是相同的种子。


  其它随机数分布

  生成随机实数,在以往的C中使用rand()/RAND_MAX来获取实数的方法是常用但错误的,原因是该表达式返回值得值域不是全体double。在新标准下使用uniform_real_distribution<>获得随机实数,如果<>内未加数字则默认double.

  生成非均匀随机数分布

1.正态分布  

normal_distribution<double> n(4, 1.5);//均值4,标准差1.5

2.伯努利分布(两点分布)

该分布返回一个bool,默认概率0.5

string resp;
default_random_engine e;
bernoulli_distribution b(.55);
do{bool first=b(e);cout<<(first?"we go first":"you get to go first")<<endl;}while(cin>>resp&&resp[0]=='y');}

由于引擎返回相同的随机数序列,所以我们必须在循环外声明引擎对象。否则,每步循环都会创造一个新引擎,从而每步循环都会生成相同的值。类似的,分布对象也要保持状态,因此也应该在循环外定义。

在此程序中使用bernoulli_distribution的原因是可以改变true概率,将概率改为0.55.


17.5

IO库再探

  标准库定义了一组操纵符来修改流的格式状态。一个操作符是一个函数或是一个对象,影响流的状态,并能作用于输入或输出运算符的运算对象。

当操纵符改变流的格式状态时,通常改变后的状态对所有后续的IO都生效。

	cout << "default bool values: " << true << " " << false
		<< "\nalpha bool values: " << boolalpha
		<< true << " " << false << endl;
这个时候原来用01表示的布尔值自动转化为true、false。
cout<<noboolalpha;//取消了原有的01->tf转化

	cout << "default: " << 20 << " " << 1024 << endl;
	cout << "octal: " <<oct<< 20 << " " << 1024 << endl;
	cout << "hex: " <<hex<< 20 << " " << 1024 << endl;
	cout << "decimal: " <<dec<< 20 << " " << 1024 << endl;//分别以默认、八进制、十六进制、十进制打印20和1024

操纵符hex、oct和dec只影响整形运算对象,浮点数的表示形式不受影响。

使用showbase来展示数制

cout<<showbase;	
cout << "default: " << 20 << " " << 1024 << endl;
	cout << "octal: " <<oct<< 20 << " " << 1024 << endl;
	cout << "hex: " <<hex<< 20 << " " << 1024 << endl;
	cout << "decimal: " <<dec<< 20 << " " << 1024 << endl;
cout<<noshowbase;//恢复默认状态


使用IO的precision成员或setprecision操作符来改变精度。precision是重载的。一个版本接受一个int值,将精度设定为此值,并返回旧精度值。另一个版本不接受参数,返回当前精度值。setprecision操纵符接受一个参数,用来设置精度。操纵符setprecision和其它接受参数的操纵符都定义在头文件iomanip中。

cout<<"Precision: "<<cout.preciosn()<<",Value: "<<sqrt(2.0)<<endl;
cout.precision(12);
cout<<"Precision: "<<cout.preciosn()<<",Value: "<<sqrt(2.0)<<endl;
cout<<setprecision(3);
cout<<"Precision: "<<cout.preciosn()<<",Value: "<<sqrt(2.0)<<endl;

除非需要特别控制浮点数的表示形式,否则由标准库选择计数法是最好的方式。

cout<<scientific;//科学计数法

cout<<fixed;//修正

cout<<hexfloat;//十六进制浮点数

cout<<defaultfloat;//默认状态

cout<<showpoint;//强制打印小数点

cout<<noshowpoint;恢复

基数大小写

cout<<uppercase;

cout<<nouppercase;

补出空白

setw

left

right

internal

setfill

操作符noskipws保留原输入的空格

char ch;
cin>>noskipws;//没有的话所有空格被忽略
while(cin>>ch)
{
cout<<ch;
}
cin>>skipws;

由于未格式化的IO使用极不安全所以暂且跳过。


流随机访问

随机IO的特性基于系统。由于istream和ostream不支持随机访问,所以一下讨论只针对fstream和sstream.

seek和tell函数,分别表示查找和告知,根据put和get又分为

tellg()、tellp()返回输入或输出流当前位置

seekg(pos).seekp(pos)在一个输入流或输出流中将标记重定位到给定位置的地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值