Python项目实战之-数字转为各种货币的读法


项目实战一: 数字转换为各种货币读法

说道字符串的各种转换,其实有各种工具都可以实现。但对于初学者来说,自己亲手去做时,又是另外一回事儿 ? ,写这边博客的目的有三点:

  • 第一 , 巩固自身的知识 , 做一个小实例;
  • 第二 , 也希望帮到需要帮助的小伙伴 ? ;
  • 第三 , 本身水平也有限 , 仍有许多不足之处 , 由于时间仓促 ,还没来得及对代码进行优化 , 希望路过的大牛能指点一二 ? 。
一、 实验环境
	1. python 3.0 +以上
	2. Windows 操作系统下
二、 实验工具
	1. 包括但不限于: pycharm 2019 或者 pycharm 2017
三、所用模块(第三方库)
	1. 基础模块 easygui 、time
	2. 拓展模块 pywin32 、 pyinstaller 
	3. * 更多 os 、 sys [用于异常处理时进程的自启]
四、 其他
	1. 程序打包 :pyinstaller -F python_programming_name.py
	2. 组件 :ccbox()、choicebox()、buttonbox()

功能展示

  • 程序已经简单的打包好了,下面展示一下这个还很粗糙的程序 ?
  • 1st ? 点击打包好的 .exe 可执行程序
    在这里插入图片描述
  • 2st ? 弹出两个窗口 ,我们先来看一下 第一个功能 : [人民币]
    在这里插入图片描述

3st 继续进行 ? .
在这里插入图片描述

4st 要我们输入数字 ,那就随便一个吧 ? .
在这里插入图片描述
在这里插入图片描述
很人性的弹出一个询问的选择窗口 ? .

  • 5st ? 又回到这个界面了 ,在试试其它的
    在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

  • Ost ?
    在这里插入图片描述

在这里插入图片描述

  • End ? 试一下极端的 :
  1. 直接敲回车或其它字符在这里插入图片描述
  2. 其它选项
    在这里插入图片描述
    嗯 ,? 这里就等小伙伴门自己来完善 ,或者添加其它功能(如果感兴趣的话 ?)

到目前为止,界面相对还算友好的



一、思路分析

中所周知,完成一件简单的事情,只要有想法,即时便可以;但是要做好一件相对复杂的事情,光有想法还不够,地球上几十亿人,有相同想法或者相似的想法何止你一个,但是有能力、有需求、并将之付诸行动的没有多少(相对于庞大的人口基数)。更何况是做一个项目。因此,我们需要有计划地按照我们的思路来一步步进行。


(一)、需求分析

初学者用于练习、巩固基础知识。包括但不限于:逻辑,语法,基本的函数定义、类定义及调用 ,常用模块的安装、导入和使用,小实例的准备和实现方法与步骤 ,debug等。

(二)、功能

(未完成的可按照已完成的进行相应拓展)

功能一 :转换为 [RMB] 读法

  • 将数字转换为RMB的阿拉伯数字和大写读法【单位:元】
  • 将数字将数字转换为RMB的阿拉伯数字和大写读法【单位:万元】
  • 将数字将数字转换为RMB的阿拉伯数字和大写读法【单位:亿元】

    功能二 :转换为 [US$] 读法

  • 将数字将数字转换为US$的阿拉伯数字和大写读法【单位:美元】
  • 将数字将数字转换为US$的阿拉伯数字和大写读法【单位:千美元】
  • 将数字将数字转换为US$的阿拉伯数字和大写读法【单位:百万美元】
  • 将数字将数字转换为US$的阿拉伯数字和大写读法【单位:十亿美元】

    其他类似功能自行拓展 比如 其他国家的货币各个国家的汇率货币之间的换算

(三)、思路

  • 第一将从键盘接收的信息进行格式化,处理为所需要的数据。( input()接收的是字符串 )

    直接用float()强制转换便可

  • 第二将整数和小数部分进行分离。(因为读法有所差异)

    这两步相对容易很多,用int()直接将这个浮点数强制类型转换成一个整数,得到我们所需的整数部分;再用作差法,[浮点数] - [整数部分] = [小数部分]。

    出于习惯,都是保留两位小数,多余的意义不大。这里将用到round(),这样会产生一些小问题,将在实例中进行细说。

  • 第三将各位的数据进行分离,依次转换为大写的中文格式数字,并在相应位置加上单位。

    我在这里用 迭代法 进行意义置换

    那么如何加上单位呢 ,不难发现,中国的读法习惯是 每隔四位为一个单元 ,即 :万 、亿 。这样一来,思路更加清晰了,将整数划分为三个部分 (在以【元】为单位只考虑12位的情况,以【万元】和【亿元】为单位是类似,相应处理后的整数部分都应不多于12位)
    如果这节 4 位数字出现在 1~4 位,则后面添加单位“元”;
    如果这节 4 位数字出现在 5~8 位,则后面添加单位“万”;
    如果这节 4 位数字出现在 9~12 位,则后面添加单位“亿”;

    我们在实现的时候便可以把其以4位为一个节点进行转换。


二、实现功能

这里 , 我把每个功能都定义为一个单独的类,在类里进行实现 。
类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。
即:

class class_name(object):
# 说明 :与python2不同的是,其实在python3中,class()是默认继承object()的
# 这里为规范 和 清晰思路(初学)考虑而这样写
  • 每个类都继承了 object 。
    为什么要继承object类呢?目的是便于统一操作。继承object类是为了让自己定义的类拥有更多的属性。
  • 主要区别:
    class_name()类不继承object,则只拥有 docmodule 和自定义的 name 变量,这个类的命名空间只有三个对象可以操作。
    class_name()类继承了object,拥有了更多的可操作的对象,这些都是类中的高级特性。如:
    [
    class , delattr , dict , doc , format , getattribute,
    hash , init , module , new , reduce , reduce_ex , repr ,
    setattr , sizeof , str , subclasshook , weakref , name
    ]

(一)、结构框架

其他申明:

  • 关于__init__方法,它的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,可以把各种属性绑定到self,这样self就指向创建的实例本身。有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
  • 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。
# 1、将数字转换为RMB的阿拉伯数字和大写读法【单位:元】
class rmb_ShuYuan_Transform(object):
	def __init__(self):
		pass
	def isolate(self,num):
		pass
	def four_to_hanstr(self,num_str): 
		pass
	def fraction_to_str(self,num_str):
		pass
	def integer_to_str(self,num_str): 
		pass
	def main(self):
		pass
		
# 2、将数字将数字转换为RMB的阿拉伯数字和大写读法【单位:万元】
class rmb_ShuWanYuan_Transform(object):
	pass
	
# 3、将数字将数字转换为RMB的阿拉伯数字和大写读法【单位:亿元】
class rmb_ShuYiYuan_Transform(object):
	pass
	
# 4、将数字将数字转换为US$的阿拉伯数字和大写读法【单位:美元】
class US_NumDollars_Transform(object):
	pass
	
# 5、 将数字将数字转换为US$的阿拉伯数字和大写读法【单位:千美元】
class US_NumThousandDollars_Transform(object):
	pass
	
# 8、将数字将数字转换为US$的阿拉伯数字和大写读法【单位:百万美元】
class US_NumMillionDollars_Transform(object):
	pass
	
# 9、 将数字将数字转换为US$的阿拉伯数字和大写读法【单位:十亿美元】
class US_NumBillionDollars_Transform(object):
	pass
	
# 10、类的调用功能
def Menu():
	pass

(二)、具体实现


功能一 、转换为 [RMB] 读法
  • 1. 定义 【数值—>[元] 人民币】(RMB) 的类 :rmb_ShuYuan_Transform(object)
class rmb_ShuYuan_Transform(object):
	# 这里是具体方法(函数)
rmb_ShuYuan_Spider = rmb_ShuYuan_Transform()
# rmb_ShuYuan_Spider.main()  # 进行单独测试时 , 可自行去掉注释符号 [#] ,调用里面的    main()
  1. 定义 __init __ () 方法, 将其中的属性绑定到self , 在同一个类中通过self进行调用

    初始化han_list[](中文大写数字) 、 unit_list[](4字节划分单位) 两个列表

    def __init__(self): 	
      self.han_list = ["零", "壹", "贰", "叁", "肆", \
                  "伍", "陆", "柒", "捌", "玖"]
      self.unit_list = ["十", "百", "千"]
    
    1. 定义 isolate() 方法,将接收到的信息进行格式化

    说明

    • 主要功能 :
      分离出输入的浮点数的 [整数部分][小数部分]
    • 处理方法 :
      利用 int() 强制类型转换作差法
    • 处理结果 :
      返回两个值(字符串),integer(整数部分) 和 fraction(小数部分[经 过处理后的整数]) 。
    def isolate(self,num):
      integer = int(num)
      a_num = (num - integer) * 100
      b_num = int(a_num)
      if b_num == 99 and a_num - b_num >= 0.5:  # 处理小数四舍五入到整数部分的bug,方法不止一种,欢迎留言讨论^_^
          integer += 1
          fraction = 0
      else:
          # 浮点数减去整数部分,得到小数部分,小数部分乘以100后再取整得到2位小数
          fraction = round((num - integer) * 100)  # 等同于int(num - integer) ## 这一句会有bug, 它不能处理小数部分四舍五入到整数部分,所以在前面加了if语句处理
      if fraction == 0: fraction = ""  # 确保本身输入的没有小数,而在分离的时候产生多余的“0”(其实仍然有问题,比如本身输入的是一个小数)
      # 下面把整数转换为字符串
      return (str(integer), str(fraction))
    
    1. 定义 four_to_hanstr() 方法,将接收到的信息进行大小写的转换

    说明

    • 主要功能 :
      把一个四位 [数字字符串] 的变成 [汉字字符串]
    • 处理方法 :
      利用 for 迭代
    • 处理结果 :
      返回 result(大写数字字符串)。
    def four_to_hanstr(self,num_str):   # 这里的四位其实不是这里的,是传进来的的num_str参数是一个四位或更少的数值;或者说是调用的时候处理的是四位或更少的数值
       result = ""
       num_len = len(num_str)
       # 依次遍历数字字符串的每一位数字
       for i in range(num_len):
           # 把字符串转成数值
           num = int(num_str[i])
           # 如果不是最后一位数字,而且数字不是零,则需要添加单位(千、百、十)
           if i != num_len - 1 and num != 0:
               result += self.han_list[num] + self.unit_list[num_len - 2 - i]
           # 否则不要添加单位
           else:
               result += self.han_list[num]
       return result
    
    1. 定义 fraction_to_str() 方法, 处理接收到的 小数部分 ,将其进行【阿拉伯数字–>中文大写数字】的转换 , 在相应位置附上单位

    说明

    • 主要功能 :(以角(分)为单位进行转换:)
      若小数部分存在,则将其转换为RMB大写格式,加上货币单位,并返回;
      否则,返回“整”
    • 处理方法 :
      利用 [if] 、[elif] 及 [if 语句的 嵌套]
    • 处理结果 :
      返回 result(大写数字字符串+单位)。
    def fraction_to_str(self,num_str):  # 单位 角、分
       str_len = len(num_str)
       # 注:num_str中的数据是字符串格式
       if str_len == 0:
           """"
                   这个条件似乎是多余的,因为尽管传进来的的是整数,但是在做整数和小数分离的过程会产生“0”,
               进而其小数长度必定不为“0”。
                   解决:(其实也不存在解决,因为本身也没有多大问题,只是让你更清楚,让结构更加完整)
                   在定义函数isolate()时加入,if fraction == 0:fraction = ""  ,
               确保本身输入的没有小数,而在分离的时候产生多余的“0”
           """
           return "整"
       elif str_len == 1:
           if num_str != "0":
               return self.four_to_hanstr(num_str) + "角"
           else:
               return "整"
       elif str_len == 2 and num_str[-1] == "0":
           return \
               self.four_to_hanstr(num_str[0]) + "角"
       else:
           return \
               self.four_to_hanstr(num_str[0]) + "角" + \
               self.four_to_hanstr(num_str[-1]) + "分"
    
    1. 定义 integer_to_str() 方法, 处理接收到的 整数部分,将其进行【阿拉伯数字–>中文大写数字】的转换 , 在相应位置附上单位

    说明

    • 主要功能 :(以元(¥)为单位进行转换:)
      将整数部分的数字字符串变成汉字字符串
    • 处理方法 :
      利用 [if] 、[elif] 及 [if 语句的 嵌套]
    • 处理结果 :
      返回 result(大写数字字符串+单位)。
    def integer_to_str(self,num_str):  # 单位元
       str_len = len(num_str)
       if str_len > 12:
       	   print("\n###>该数字超出计量范围!<###\n请重新输入整数部分为12(包含)以内的数字\n")
           self.main()
           return
       # 如果大于8位,包含单位亿
       elif str_len > 8:
           return self.four_to_hanstr(num_str[:-8]) + "亿 " + \
                  self.four_to_hanstr(num_str[-8: -4]) + "万 " + \
                  self.four_to_hanstr(num_str[-4:]) + "元 "
       # 如果大于4位,包含单位万
       elif str_len > 4:
           return self.four_to_hanstr(num_str[:-4]) + "万 " + \
                  self.four_to_hanstr(num_str[-4:]) + "元 "
       else:
           return self.four_to_hanstr(num_str) + "元 "
    
    1. 定义 main() 方法,主函数
    def main(self):
       # ---进行测试---
       # 从键盘输入一个数字(字符串)
       num = float(input("请从键盘输入一个数字: "))
       
       # 调用函数divide(),将输入的的[整数、浮点数](字符串)分解成整数部分和小数部分
       integer, fraction = divide(num)
       
       
       #调用函数integer_to_str()将支持范围内的整数转换为大写并附上货币单位;
       transform_integer = integer_to_str(integer)
       #调用函数fraction_to_str()将小数部分(若存在)转换为大写并附上货币单位
       transform_fraction = fraction_to_str(fraction)
       
       print("\t\t货币类型:","RMB")
       print("小写格式:",integer + "." + fraction ,"¥")
       print("大写格式:",transform_integer + transform_fraction)
    
    • 测试
    先看一下这一部分的效果效果如何 :
    

    [测试 1 ]: 输入123.56 在这里插入图片描述
    没问题 ?
    [测试 2 ]: 输入44885.786
    在这里插入图片描述
    没问题 ?
    [测试 3 ]: 输入885522449.883
    在这里插入图片描述
    没问题 ?
    [测试 4 ]: 输入1122334455660.1
    在这里插入图片描述
    gg思密达 ? ,这里是不是跟自己预想的不一样?
    按照之前的设定,如果超出表示范围,直接打印【超出范围】的字符串,而不是报错吧 。具体如 何处理 ,将在【三、拓展与部分优化】详细说明。
    给出的 [源码] 并不会有提到的问题 ❤️

    除此之外,其实还有个小问题,就是小数部分四舍五入,即0.99x ,当x>5时。进位 “1” 被丢弃 , 显示 0.100
    我们来测试一下:
    在这里插入图片描述
    果真如此。 ? ,对于这个问题,我做了如下的改进:

        def isolate(self,num):
            # 将一个浮点数(字符串)强制类型转换为int型,即得到它的整数部分
            integer = int(num)
            
            # <改进从这里开始>  *******************************************
            a_num = (num - integer) * 100
            b_num = int(a_num)
            if b_num == 99 and a_num - b_num >= 0.5:  # 处理小数四舍五入到整数部分的bug,方法不止一种,欢迎留言讨论^_^
                integer += 1
                fraction = 0
            else:
                # 浮点数减去整数部分,得到小数部分,小数部分乘以100后再取整得到2位小数
                fraction = round(
                    (num - integer) * 100)  # 等同于int(num - integer) ## 这一句会有bug, 它不能处理小数部分四舍五入到整数部分,所以在前面加了if语句处理
            # <改进到这来结束>  *****************************************************************************
            
            if fraction == 0: fraction = ""  # 确保本身输入的没有小数,而在分离的时候产生多余的“0”(其实仍然有问题,比如本身输入的是一个小数)
            # 下面把整数转换为字符串
            return (str(integer), str(fraction))
    

    改进说明:

    • 处理方法:当遇到需要小数进位到整数的情况 ,通过 if 语句判断 ,符号进位条件 ,则变量重新赋为新值, 当不满足时,触发 else 语句 ,则按照原先的编写即可。

    下面进行测试
    在这里插入图片描述
    哈 ? ,完美解决。

以上部分的源码
class rmb_ShuYuan_Transform(object):
    def __init__(self):
        self.han_list = ["零" , "壹" , "贰" , "叁" , "肆" ,\
            "伍" , "陆" , "柒" , "捌" , "玖"]
        self.unit_list = ["十" , "百" , "千"]

    def isolate(self,num):
        # 将一个浮点数(字符串)强制类型转换为int型,即得到它的整数部分
        integer = int(num)
        a_num = (num - integer) * 100
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值