您的位置:首页 > 编程语言

算法学习与代码实现1——开始、生成随机数

2016-05-08 16:48 615 查看

开端

作为一个非科班出身的程序猿,算法始终是个软肋。之前倒也抽时间断断续续看了点算法的书,但基本过目即忘,可能每个算法都实际实现以下,编写下练习代码才能更好的学习。于是在github上创建了一个仓库,用来一个个实现算法。置于语言的选择,都说语言不过是工具,算法才是核心,那么就多用几种语言来实现吧。其实我会的语言也不多,c/c++可能还好,再就是个初学者阶段的Python,在实现算法的过程中,也能练习下这些语言的使用,一箭双雕呀,哈哈,有点小激动呢。

github上的仓库地址如下:

git@github.com:haoranzeus/algorithms_study.git

既然是在世界流行的github上创建仓库,上面我也尽量使用英文,虽然我这英文水平有点惨不忍睹。

好,让我们开始吧。

随机数生成

算法书上面开始介绍的算法必然是排序,要排序就要有数可排,那么就先写一个生成随机数的程序吧。

需求如下:

1. 生成随机数写入文件。

2. 制定生成整数还是浮点数。

3. 指定生成的数的大小范围。

4. 指定保存到文件的数之间的分隔符。

Python实现

这里我创建一个mypackage的路径,用于存放以后可能有复用价值的包,关于这种向文件里写数据的功能,就放到这里的myio.py里面。然后random_number_generator/random_number_generator.py用于实现生成随机数。

生成随机数的代码如下:

from random import uniform, randint
def randNumGenerator(numbType, numMin, numMax, numb):
"""
numbType: an "int" for initerator, and a "float" for float number.
numMin: The nimimum for the number generatored.
numMax: the maximum for the number generatored.
numb: the number of numbers generatored.
"""
if numbType == "int":
generator = randint
elif numbType == "float":
generator = uniform
else:
raise AttributeError("invalid value for type: %s" % numbType)
numMin = int(numMin)
numMax = int(numMax)
numb   = int(numb)

while numb > 0:
yield generator(numMin, numMax);
numb -= 1


这段代码采用标准标准包random中的uniform和randint分别实现生成随机浮点数和随机整数。

参数分别表示要生成的数的类型、最小值、最大值以及要生成的 数据个数。

该函数返回生成器,每次生成一个随机数,直至生成了指定的个数。

然后是该函数的单元测试:

import unittest
class TestRandNumGenerator(unittest.TestCase):

def test_generatorInit(self):
i = 0
for n in randNumGenerator("int", 0, 10000, 20):
i += 1
self.assertTrue(n >= 0)
self.assertTrue(n <= 10000)
self.assertTrue(isinstance(n, int))

self.assertEqual(i, 20)

def test_generatorFloat(self):
i = 0
for n in randNumGenerator("float", 0, 10000, 20):
i += 1
self.assertTrue(n >= 0)
self.assertTrue(n <= 10000)
self.assertTrue(isinstance(n, float))

self.assertEqual(i, 20)

def test_typeError(self):
with self.assertRaises(AttributeError):
g = randNumGenerator("unknowType", 0, 10000, 20)
g.__next__()


使用unittest进行,方法是定义一个继承自unittest.TestCase的类,然后定义以test_开头的类方法,这种方法会自动运行。unittest.TestCase提供了很多断言,具体可以看帮助手册,这里我使用了assertTrue和assertEqual。值得注意的是错误的测试,使用with self.assertRases(),然后在里面引发错误,unittest会捕捉这个期待的错误。

unittest运行有两种方法,一种是添加代码:

if __name__ == '__main__':
unittest.main()


这样就默认运行单元测试了。但是我想让他默认运行的是写入文件的功能,所以采用另一种运行单元测试的方式:

python3 -m unittest random_number_generator

接着是写入文件的操作。我将其放到mypackage/myio.py中,代码如下:

class MyIo(object):
def __init__(self, path):
self.path = path

def writeSeperated(self, generator, separator = " "):
"""
generator: a generator to generate fragments to write in file
separator: separator between fragments.
"""

with open(self.path, "w") as f:
for frag in generator:
f.write(str(frag))
f.write(str(separator))

f.close()


所有文件操作都放到一个MyIo的类中,初始化时会接收一个参数,表示文件路径。

这种以分隔符分隔数据写入文件的方法定义为writeSeperated,第一个参数是一个迭代器,用于生成要写入的数据,第二个参数是分隔符,默认是空格。

最后就是用生成随机数的迭代器带入到写入文件的函数中,一个交互式的生成随机数文件的函数如下:

def writeToFile():
path = input("Please input the whole path of file:\n")
numType = input('You want to generate "int" or "float"?\ntype "int" or "float":\n')
minNum = input('the minimum value of the generated numbers:')
maxNum = input('the maximum value of the generated numbers:')
numb = input('the number you want to generate:')
separator = input('the separator:')
import sys
sys.path.append("..")
from mypackage.myio import MyIo
myio = MyIo(path)

myio.writeSeperated(randNumGenerator(numType, minNum, maxNum, numb))


这个函数会以交互式的形式获取文件的路径、数据的类型、最大最小值、要生成的随机数的个数,以及分隔符。调用这个函数:

if __name__ == '__main__':
writeToFile()


C语言实现

怕麻烦,C语言的实现直接一个文件搞定了,位于c/random_number_generator/main.c,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

int main()
{
char path[100];
char type[10];
int min;
int max;
int numb;
char separator[10];

printf("Please input the whole path of file:\n");
scanf("%s", path);
printf("You want to generate \"int\" or \"float\"?\ntype \"int\" or \"float\":\n");
scanf("%s", type);
if ( strncmp("int", type, 3) && strncmp("float", type, 5)) {
printf("ERROR: unknow type : %s\n", type);
return 0;
}
printf("the minimum value of the generated numbers:");
scanf("%d", &min);
printf("the maximum value of the generated numbers:");
scanf("%d", &max);
printf("the number you want to generate:");
scanf("%d", &numb);
printf("the separator:");
scanf("%s", separator);

FILE * f = fopen(path, "w");
srand((unsigned)time(NULL));
int range = max - min;
for (int i = 0; i < numb; i++) {
if ( !strncmp("int", type, 3) )
fprintf(f, "%d%s", rand() % range + min, separator);
else if ( !strncmp("float", type, 5) ) {
double rdnumb = (rand() % (range * 100) / 100.00) + min;
fprintf(f, "%f%s", rdnumb, separator);
}
}
fclose(f);
}


首先是交互式获取用户输入,包括文件路径、生成的数据类型(int和float),生成的数的范围,要生成的数据个数,分隔符。
生成随机数使用srand和rand,前者用time(NULL)作为种子,后者用于产生随机数。这里做一点说明,rand生成的是0~RAND_MAX的整数,RAND_MAX在各个平台上大小不同。要获取一个范围的随机数可以对其进行取余操作。
文件的写入使用fprintf进行格式化写入。

本文代码托管于:
https://github.com/haoranzeus/algorithms_study
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: