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

开端

作为一个非科班出身的程序猿,算法始终是个软肋。之前倒也抽时间断断续续看了点算法的书,但基本过目即忘,可能每个算法都实际实现以下,编写下练习代码才能更好的学习。于是在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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值