博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
机器学习笔记(3)---K-近邻算法(1)---约会对象魅力程度分类
阅读量:4011 次
发布时间:2019-05-24

本文共 15267 字,大约阅读时间需要 50 分钟。

参考资料

《机器学习实战》,Machine Learning in Action,本文中简称MLiA

《机器学习》周志华,本文简称西瓜书
《Web安全之机器学习》刘焱著,本文中简称WSML(Web Security in Machine Learning,该英文翻译只为记录方便,是本人杜撰的,仅限本系列文章使用)

转载请注明出处:

前言

因为之前不知道怎么把机器学习的知识用起来,所以心理很没底,看了近一年的数学基础,感觉也没有什么长进,而看了《机器学习实战》第2章k-近邻算法后发现,原来机器学习也可以这么简单。

本算法真不需要什么高深的数学公式,只要会一些基础的矩阵知识就可以了。代码里Numpy ndarray相关的东西看起来挺复杂的,但打出来调试后也就不会觉得难了。
另外我发现了自己学习的方法(其实原来也发现了,只是没总结),先跟着书把代码敲一遍(或者直接复制粘贴),这个时候不要去看书上关于代码的解释,因为看不懂,看不懂会影响学习心情,所以不要看。先把代码运行一遍看结果,运行成功后再看不理解的代码,边看边调试,比看书本上关于代码的解释效果好多了。

本次学习以实践为主,理论为辅。为了加深对KNN算法的理解,我学了以下内容,虽然很多,但我相信如果大家对以下内容都理解了,那么KNN算法也就掌握了。主要内容有以下五,我会分五篇文章完成学习记录。

  1. 使用KNN算法对约会对象魅力程度分类
  2. 使用sklearn库中的KNN算法对约会对象魅力程度分类
  3. 使用KNN算法完成手写识别系统
  4. 使用KNN算法完成西瓜分类
  5. 使用KNN算法检测Linux系统异常操作

本篇文章先描述K-近邻算法核心思想,再记录使用KNN算法对约会对象魅力程度分类的代码的理解。

K-近邻算法

所谓的k-近邻算法(K-Nearest Neighbor,简称KNN)是这样的,首先要有一批已知的样本数据的特征(比如MLiA举的交友例子,交友对象的年飞行里程、玩游戏占的时间比和周消费的冰淇淋公升数),并且知道这些数据的标签(不喜欢的人、魅力一般的人和极具魅力的人),然后输入不带标签的新数据(知道这个人的年飞行里程、玩游戏占的时间比和周消费的冰淇淋公升数,但不知道它属于哪一类),拿这个新数据和样本数据比较,算出和新数据最相似的k个数据(k可自定义),然后看这k个数据中出现最多的类型,新数据就属于这一类。

所以整体思想是很简单的,但这里面会延伸出三个问题:
1. 新数据和样本数据距离计算公式是怎样的?
2. 如果某一项属性数据太大,这样在计算距离时其它属性就不起作用了,但是其它属性也是一样重要的,那怎么办?这就需要做归一化处理。
3. 如何测试算法的准确性。这里会拿样本数据的前x%用于作为直接的样本(因为k-近邻算法没有训练数据概念,这里姑且叫它训练数据),后面的1-x%数据拿来测试(叫测试数据)。

相关概念

本节内容可先跳过,如后续看的不明白可回来查看相关概念。

KNN算法中的训练数据和一般意义上的训练数据不太一样。因为在KNN中实际上是不需要训练数据的,只需要知道一些已知的带标签的数据就可以了,后续新来的数据只要和这些已知标签的数据做运算就可以了。

所以这里的相关解释如下:

  • 样本数据

    所有带标签的数据。其中一部分拿来用做训练数据(比如80%),一部分拿来当测试数据(比如剩下的20%)。

  • 训练数据

    带标签的标本数据,实际上是给KNN算法本身使用的。当测试数据或待预测数据来了时和这些数据做运算使用。

  • 测试数据

    测试数据也是带标签的,是在样本数据中预留出来的,用以检测算法正确率的。当算法已经设计好后,给算法传入这些测试数据,然后取得算法返回的预测结果,并把这些预测结果和已知的标签做对比,从而计算出算法的正确率。

使用KNN算法对约会对象魅力程度分类

先来看下最终效果,有一个直观的认识。

最终效果

最终效果如下。输入年飞行里程、玩游戏占的时间比和周消费的冰淇淋公升数,程序输出这个人的魅力程度。

最终效果

代码分析

代码分析请直接看注释。

def classifyPerson():    resultList = ['没有魅力', '魅力一般', '极具魅力']    ffMiles = float(input("每年飞行公里数?"))    percentTats=float(input("打游戏耗费时间的百分比?"))    iceCream = float(input("每周消费的冰激凌?"))    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    normMat, ranges, minVals = autoNorm(datingDataMat)    inArr = np.array([ffMiles,percentTats,iceCream])    classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)    print("这个人:", resultList[classifierResult-1])#从文件中获取数据,并格式化成Numpy数组。#returnMat[]数组用于存放样本的属性。#classLabelVector[]用于存放样本的类别def file2matrix(filename):    fr = open(filename)    numberOfLines = len(fr.readlines())         #1000    returnMat = np.zeros((numberOfLines,3))        #创建numberOfLines行,3列矩阵,初始化为0.    classLabelVector = []                       #用于存放第四列的的值。    fr = open(filename)    index = 0    for line in fr.readlines():        line = line.strip()        listFromLine = line.split('\t')        returnMat[index,:] = listFromLine[0:3] #因为index是会自增的,所以数据会往returnMat上增。        classLabelVector.append(int(listFromLine[-1]))        index += 1    return returnMat,classLabelVector# returnMat={ndarray} [[  4.09200000e+04   8.32697600e+00   9.53952000e-01]#  [  1.44880000e+04   7.15346900e+00   1.67390400e+00]#  [  2.60520000e+04   1.44187100e+00   8.05124000e-01]#  ...,#  [  2.65750000e+04   1.06501020e+01   8.66627000e-01]#  [  4.81110000e+04   9.13452800e+00   7.28045000e-01]#  [  4.37570000e+04   7.88260100e+00   1.33244600e+00]]#classLabelVector={list}[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1,……]#归一化处理公式:newValue=(oldValue-min)/(max-min)def autoNorm(dataSet):    #dataSet是1000行3列的数据。    minVals = dataSet.min(0)    maxVals = dataSet.max(0)    ranges = maxVals - minVals    normDataSet = np.zeros(np.shape(dataSet))#shape取ndarray dataSet的大小(维度),然后创建一个一样大小的ndarray,并以0初始化。    m = dataSet.shape[0]#取0维大小,1000行。    normDataSet = dataSet - np.tile(minVals, (m,1))#做(oldValue-min)操作    normDataSet = normDataSet/np.tile(ranges, (m,1))   #element wise divide    return normDataSet, ranges, minVals# normDataSet={ndarray}[[ 0.44832535  0.39805139  0.56233353]#  [ 0.15873259  0.34195467  0.98724416]#  [ 0.28542943  0.06892523  0.47449629]#  ...,#  [ 0.29115949  0.50910294  0.51079493]#  [ 0.52711097  0.43665451  0.4290048 ]#  [ 0.47940793  0.3768091   0.78571804]]# ranges={ndarray}[  9.12730000e+04   2.09193490e+01   1.69436100e+00]# minVals={ndarray}[ 0.        0.        0.001156]#classify0的作用:#给定一个输入List inX,可以是n维,这个inX一般存放待分类的条目的属性值,然后和已知数据集(因为是已知的,所以标签类别也是已知的)相比(通过两点差的平方和再开根号),算出最近的k个,这k个数据中出现次数就是最多的类别就是新数据的类别。#输出即是该条目的类别。#这个分类函数是支持多维的,而该函数里的注释是基于2维写的。#2维情况的输入值:#inX=[0, 0]#dataSet= #这个即是已知的数据属性(这里有4条数据,每条数据有两个属性)# [[ 1.   1.1]#  [ 1.   1. ]#  [ 0.   0. ]#  [ 0.   0.1]]#labels=['A', 'A', 'B', 'B'] #这个就是已知的数据的类别#k=3 表示只取最近的3个做比较,#输出A或B。def classify0(inX, dataSet, labels, k):    dataSetSize = dataSet.shape[0] #计算dataSet有多少行,这里的0维指x行    diffMat = np.tile(inX, (dataSetSize,1)) - dataSet#生成和dataSet一样大小的数组,其每行的成员(x,y)都是inX的x,y减dataSet对应行的x,y。    sqDiffMat = diffMat**2 #对每个成员做平方操作。    sqDistances = sqDiffMat.sum(axis=1) #把每行的两个值相加    distances = sqDistances**0.5 #再把相加的值开方,就算出了距离    sortedDistIndicies = distances.argsort() #然后再从小到大排序,并记下相应的下标。    classCount={}    for i in range(k):#这里是字典相关的操作,即统计'A','B'的次数(前3名中),其中'A','B’为key,次数为value。        voteIlabel = labels[sortedDistIndicies[i]]        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #这种都是字典操作,先从字典中取出'A'的次数,然后加1,再赋值给'A'对应的值。    #上述代码结束后,classCount字典的值为:{'B': 2, 'A': 1}    sortedClassCount = sorted(iter(classCount.items()), key=op.itemgetter(1), reverse=True)    #sorted可对迭代类型排序    #operator是python的一个模块,其中itemgetter函数可以获得对象不同维度的数据,参数为维度的索引值    #比如[('B', 2), ('A', 1)],那么op.itemgetter(1)就是以第2维来排序,即以后面的数字来排序。    #reverse是否反转,默认排序结果是从小到大,这里想要的是从大到小。    return sortedClassCount[0][0]#这里取第0行第0列。

测试分类算法的正确性

上一步已经实现了算法的核心功能。其实在这分类算法出来之前,应该对分类算法做一个测试,看其正确率有多少。

#用来测试分类算法的正确性def datingClassTest():    hoRatio = 0.10      #预留的数据百分比用来测试分类器。    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')           normMat, ranges, minVals = autoNorm(datingDataMat)    m = normMat.shape[0] #算出0维大小,一共1000条    numTestVecs = int(m*hoRatio) #预留数据的后面数据用来训练样本,这里算这些数据的起始位置。预留数据用来和这些训练样本比较,计算距离。    errorCount = 0.0    for i in range(numTestVecs):        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)        #classifierResult是使用分类器测出来的结果,拿此结果和真实结果(datingLabels[i])对比,如果一样表示预测正确。        #normMat[i,:],表示norMat的第i行,第i取所有(:冒号表示所有),具体可看my_4_1_intro.py二维数组切片。        #normMat[numTestVecs:m,:]表示从训练数据位置numTestVecs开始到最后一条数据m为止。        print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))        if (classifierResult != datingLabels[i]): errorCount += 1.0      #统计错误数。    print("the total error rate is: %f" % (errorCount/float(numTestVecs)))  #统计错误率。    print(errorCount)

运行结果如下图所示,可知错误率为5%,可以调整预留数据hoRatio的比例再试错误率。

测试结果

如何画图直观展示数据

这里展示的程序没对数据做归一化处理,展示的时候只取飞行公里数和玩游戏时间,即datingDataMat第0列和第1列数据。当然也可取其它组合试试,但是分类效果不好。

#从文本文件中解析数据,并使用Matplotlib画图展示。def file2matrix_test():    #2.2.1节代码,从文本文件中解析数据。    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    print(datingDataMat) #数据前三列的矩阵    print(datingLabels) #第四列值存放在list中。    #2.2.2使用Matplotlib创建散点图。    fig = plt.figure()    ax = fig.add_subplot(111)    num_show=0#需要从矩阵的第几行数据开始展示,0为展示所有    ax.scatter(datingDataMat[num_show:,0], datingDataMat[num_show:,1], 15.0*np.array(datingLabels[num_show:]), 15.0*np.array(datingLabels[num_show:]))    #用datingLabels类型标注不同的颜色,scatter的具体用法再学。    plt.show()    #这里还有一个小问题没有解决,就是显示在图上的颜色没有标注到底是属于哪一类的,这个可在后续学Matplotlib时再完善。

运行结果:

Matplotlib展示结果

完整代码

以下代码是本实例完成代码,使用python3.6可直接运行,当然需要安装相应的库了,不会的话可上网找下。

#coding:utf-8#autho:pan_limin#date:2018.1.22#python3.6#说明:本程序参考《机器学习实践》第2章KNN相关教程,源码几乎是一样的,主要加入自己的一些学习备注。import numpy as np #这里和书上导入的方式不太一样,使用我这种方式更容易理解。import operator as opimport matplotlibimport matplotlib.pyplot as plt#classify0的作用:#给定一个输入List inX,可以是n维,这个inX一般存放待分类的条目的属性值,然后和已知数据集(因为是已知的,所以标签类别也是已知的)相比(通过两点差的平方和再开根号),和哪几个近就属于哪类。#输出即是该条目的类别。#这个分类函数是支持多维的,而该函数里的注释是基于2维写的。#2维情况的输入值:#inX=[0, 0]#dataSet=# [[ 1.   1.1]#  [ 1.   1. ]#  [ 0.   0. ]#  [ 0.   0.1]]#labels=['A', 'A', 'B', 'B']#k=3 表示只取最近的3个做比较,#输出A或B。def classify0(inX, dataSet, labels, k):    dataSetSize = dataSet.shape[0] #计算dataSet有多少行,这里的0维指x行    diffMat = np.tile(inX, (dataSetSize,1)) - dataSet#生成和dataSet一样大小的数组,其每行的成员(x,y)都是inX的x,y减dataSet对应行的x,y。    sqDiffMat = diffMat**2 #对每个成员做平方操作。    sqDistances = sqDiffMat.sum(axis=1) #把每行的两个值相加    distances = sqDistances**0.5 #再把相加的值开方,就算出了距离    sortedDistIndicies = distances.argsort() #然后再从小到大排序,并记下相应的下标。    classCount={}    for i in range(k):#这里是字典相关的操作,即统计'A','B'的次数(前3名中),其中'A','B’为key,次数为value。        voteIlabel = labels[sortedDistIndicies[i]]        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #这种都是字典操作,先从字典中取出'A'的次数,然后加1,再赋值给'A'对应的值。    #上述代码结束后,classCount字典的值为:{'B': 2, 'A': 1}    sortedClassCount = sorted(iter(classCount.items()), key=op.itemgetter(1), reverse=True)    #sorted可对迭代类型排序    #operator是python的一个模块,其中itemgetter函数可以获得对象不同维度的数据,参数为维度的索引值    #比如[('B', 2), ('A', 1)],那么op.itemgetter(1)就是以第2维来排序,即以后面的数字来排序。    #reverse是否反转,默认排序结果是从小到大,这里想要的是从大到小。    return sortedClassCount[0][0]#这里取第0行第0列。def createDataSet():    group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])    # print(group)    lables = ['A', 'A', 'B', 'B']    return group, lablesdef createDataSet_test():    group, labels = createDataSet()#2.1.1导入数据到ndarray中。    result = classify0([0,0], group, labels, 3)#2.1.2 实现分类算法,并给定一个条目,判断此条目属于哪类。    print(result)#为了理解以上内容,做的单独测试,和正式代码没有任何关系。def createDataSet_temp_test():     inX = [0,0]     k=3     group, labels = createDataSet()     print(group)     dataSetSize = group.shape[0]#group 0维方向大小,group因为是4行3列,0维的值即为4.     print(group.shape[0]) #4     dataSet = group     print(np.tile(inX, (4,1))) #tile表示在给定的数组,在行方向重复4次,列方向重复1次。     diffMat = np.tile(inX, (dataSetSize,1)) - dataSet     print(diffMat)     sqDiffMat = diffMat**2     print(sqDiffMat)     sqDistances=sqDiffMat.sum(axis=1)     print(sqDistances)     distances = sqDistances**0.5     print(distances)     sortedDistIndicies = distances.argsort()     print(sortedDistIndicies)     classCount={}     # aa = 'B'     # print(classCount.get('B',0))     for i in range(k):#        voteIlabel = labels[sortedDistIndicies[i]]        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1     print(classCount)#classCount字典的值为:{'B': 2, 'A': 1}     print(iter(classCount.items()))     for item in iter(classCount.items()):         print(item)     sortedClassCount = sorted(iter(classCount.items()), key=op.itemgetter(1), reverse=True)     #sorted可对迭代类型排序     #operator是python的一个模块,其中itemgetter函数可以获得对象不同维度的数据,参数为维度的索引值     #比如[('B', 2), ('A', 1)],那么op.itemgetter(1)就是以第2维来排序,即以后面的数字来排序。     #reverse是否反转,默认排序结果是从小到大,这里想要的是从大到小。     print(sortedClassCount)#从文件中获取数据,并格式化成Numpy数组。#returnMat[]数组用于存放样本的属性。#classLabelVector[]用于存放样本的类别def file2matrix(filename):    fr = open(filename)    numberOfLines = len(fr.readlines())         #1000    returnMat = np.zeros((numberOfLines,3))        #创建numberOfLines行,3列矩阵,初始化为0.    classLabelVector = []                       #用于存放第四列的的值。    fr = open(filename)    index = 0    for line in fr.readlines():        line = line.strip()        listFromLine = line.split('\t')        returnMat[index,:] = listFromLine[0:3] #因为index是会自增的,所以数据会往returnMat上增。        classLabelVector.append(int(listFromLine[-1]))        index += 1    return returnMat,classLabelVector# returnMat={ndarray} [[  4.09200000e+04   8.32697600e+00   9.53952000e-01]#  [  1.44880000e+04   7.15346900e+00   1.67390400e+00]#  [  2.60520000e+04   1.44187100e+00   8.05124000e-01]#  ...,#  [  2.65750000e+04   1.06501020e+01   8.66627000e-01]#  [  4.81110000e+04   9.13452800e+00   7.28045000e-01]#  [  4.37570000e+04   7.88260100e+00   1.33244600e+00]]#classLabelVector={list}[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1,……]#归一化处理公式:newValue=(oldValue-min)/(max-min)def autoNorm(dataSet):    #dataSet是1000行3列的数据。    minVals = dataSet.min(0)    maxVals = dataSet.max(0)    ranges = maxVals - minVals    normDataSet = np.zeros(np.shape(dataSet))#shape取ndarray dataSet的大小(维度),然后创建一个一样大小的ndarray,并以0初始化。    m = dataSet.shape[0]#取0维大小,1000行。    normDataSet = dataSet - np.tile(minVals, (m,1))#做(oldValue-min)操作    normDataSet = normDataSet/np.tile(ranges, (m,1))   #element wise divide    return normDataSet, ranges, minVals# normDataSet={ndarray}[[ 0.44832535  0.39805139  0.56233353]#  [ 0.15873259  0.34195467  0.98724416]#  [ 0.28542943  0.06892523  0.47449629]#  ...,#  [ 0.29115949  0.50910294  0.51079493]#  [ 0.52711097  0.43665451  0.4290048 ]#  [ 0.47940793  0.3768091   0.78571804]]# ranges={ndarray}[  9.12730000e+04   2.09193490e+01   1.69436100e+00]# minVals={ndarray}[ 0.        0.        0.001156]#从文本文件中解析数据,并使用Matplotlib画图展示。def file2matrix_test():    #2.2.1节代码,从文本文件中解析数据。    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    print(datingDataMat) #数据前三列的矩阵    print(datingLabels) #第四列值存放在list中。    #2.2.2使用Matplotlib创建散点图。    fig = plt.figure()    ax = fig.add_subplot(111)    num_show=0#需要从矩阵的第几行数据开始展示,0为展示所有    ax.scatter(datingDataMat[num_show:,0], datingDataMat[num_show:,1], 15.0*np.array(datingLabels[num_show:]), 15.0*np.array(datingLabels[num_show:]))    #用datingLabels类型标注不同的颜色,scatter的具体用法再学。    plt.show()    #这里还有一个小问题没有解决,就是显示在图上的颜色没有标注到底是属于哪一类的,这个可在后续学Matplotlib时再完善。#归一化处理,因为有一项属性数据太大,这样在算距离时其它属性就不起作用了,但是其它属性也是一样重要的,需要要做归一化处理。def autoNorm_test():    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    normMat, ranges, minVals = autoNorm(datingDataMat)    print(normMat,'\n', ranges,'\n',minVals,'\n')#用来测试分类算法的正确性def datingClassTest():    hoRatio = 0.10      #预留的数据用来测试分类器。    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file    normMat, ranges, minVals = autoNorm(datingDataMat)    m = normMat.shape[0] #算出0维大小,一共1000条    numTestVecs = int(m*hoRatio) #预留数据的后面数据用来训练样本。预留数据用来和这些训练样本比较,计算距离。    errorCount = 0.0    for i in range(numTestVecs):        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)        #classifierResult是使用分类器测出来的结果,拿此结果和真实结果(datingLabels[i])对比,如果一样表示预测正确。        #normMat[i,:],表示norMat的第i行,第i取所有(:冒号表示所有),具体可看my_4_1_intro.py二维数组切片。        #normMat[numTestVecs:m,:]表示从训练数据位置numTestVecs开始到最后一条数据m为止        print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))        if (classifierResult != datingLabels[i]): errorCount += 1.0      #统计错误数。    print("the total error rate is: %f" % (errorCount/float(numTestVecs)))  #统计错误率。    print(errorCount)#这个代码在原书自带的源码中没找到,自己敲一遍吧。def classifyPerson():    resultList = ['没有魅力', '魅力一般', '极具魅力']    ffMiles = float(input("每年飞行公里数?"))    percentTats=float(input("打游戏耗费时间的百分比?"))    iceCream = float(input("每周消费的冰激凌?"))    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')    normMat, ranges, minVals = autoNorm(datingDataMat)    inArr = np.array([ffMiles,percentTats,iceCream])    classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)    print("这个人:", resultList[classifierResult-1])if __name__ == '__main__':    #1、2.1节代码    # createDataSet_test()    #用于学习k近领核心算法classify0()    # createDataSet_temp_test()    #2、演示2.2.1和2.2.2。 2.2.1从文本文件中解析数据,2.2.2使用Matplotlib创建散点图。    file2matrix_test()    #3、测试2.2.3    # autoNorm_test()    #4、测试2.2.4节    #有了以上知识做铺垫后,现在开始测试算法。测试算法    # datingClassTest()    #5、2.2.5完整可用系统。输入一个条目属性特征,返回这个人属于哪类。    # classifyPerson()

如有疑问之处欢迎加我微信交流,共同进步!请备注“CSDN博客”

这里写图片描述

你可能感兴趣的文章
git 常用命令
查看>>
linux位操作API
查看>>
snprintf 函数用法
查看>>
uboot.lds文件分析
查看>>
uboot start.s文件分析
查看>>
没有路由器的情况下,开发板,虚拟机Ubuntu,win10主机,三者也可以ping通
查看>>
本地服务方式搭建etcd集群
查看>>
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>
忽略图片透明区域的事件(Flex)
查看>>
AS3 Flex基础知识100条
查看>>
Flex动态获取flash资源库文件
查看>>
flex中设置Label标签文字的自动换行
查看>>
Flex 中的元数据标签
查看>>
flex4 中创建自定义弹出窗口
查看>>
01Java基础语法-11. 数据类型之间的转换
查看>>
01Java基础语法-13. if分支语句的灵活使用
查看>>
01Java基础语法-15.for循环结构
查看>>
01Java基础语法-16. while循环结构
查看>>
01Java基础语法-17. do..while循环结构
查看>>