轨道
/
Julia
Julia
/
练习
/
货币兑换
货币兑换

货币兑换

学习练习

简介

Julia 是一门通用编程语言,可用于大多数编程任务。 不过在实际使用中,主要应用场景往往是工程和科学。 快速、灵活且精密的数值计算是其设计的核心。

整数

整数是没有小数点的“整”数。

在基础概念中,我们看到可以把一个整数值赋给变量,而无需指定类型。

为了提高可读性,可以用下划线作为数字分隔符。 编译器会忽略它们。

julia> x = 3
3

julia> typeof(x)
Int64

julia> large_number = 1_234_567_890
1234567890

浮点数

毫不意外,浮点数有小数点,小数点后还有小数部分。

julia> f = 3.45
3.45

julia> typeof(f)
Float64

当然,也支持科学计数法。

julia> avogadro = 6.02e23
6.02e23

最大值和最小值可能会让你意外:

julia> typemax(Float64)
Inf

julia> typemin(Float64)
-Inf

无穷大也是一个有效值!

算术运算符

正如基础概念中讨论的那样,算术运算符大多与标准算术相同,也就是孩子们学的那种算术。 注意,乘方使用^,而不是**(两者在其他语言中都很常见)。

2 + 3  # 5 (addition)
2 - 3  # -1 (subtraction)
2 * 3  # 6 (multiplication)
8 / 2  # 4.0 (division)
8 % 3  # 2 (remainder)
2 ^ 3  # 8 (exponentiation)

不过,有几个 Julia 特有的细节值得讨论。

乘法

julia> x = 4.2
4.2

julia> 2 * x
8.4

julia> 2x
8.4

julia> 2.4x
10.08

这可能让人意外。

总是可以使用*作为中缀运算符,就像大多数其他计算机语言一样。

然而,Julia 的设计者相信,代码应该尽可能看起来像数学等式。

由于变量名必须以字母开头,在名称前加上数字(整数或浮点数)会被视为隐式乘法。

例如,如果想求球体的表面积,我们可以不写4 * pi * r * r,而是这样做:

julia> surface(r) = 4π * r^2
surface (generic function with 1 method)

julia> surface(3)
113.09733552923255

尽管 π 是内置常量,它也是一个(希腊)字母。 因此解析器仍然需要一个显式的*来把π和r分开。

除法

使用/作为中缀运算符时,即使输入是整数,结果也总是浮点数。

对于整数除法,还有更多选择。

julia> 10 / 3  # floating-point division
3.3333333333333335

julia> div(10, 3)  # integer division
3

julia> 10 ÷ 3  # synonym for div()
3

julia> 10 // 3  # rational number (fraction)
10//3

div()函数用于整数除法,结果向零截断:正数向下取整,负数向上取整。

作为同义词,我们可以使用中缀运算符÷,同样是为了让它看起来更像数学。 如果你使用能识别 Julia 的编辑器,输入\div,然后按<Tab>键。

//运算符超出了本概念的范围。 现在,我们只需说//的结果是一个“有理”数,大多数人称之为_分数_。

数字类型的转换

这通常可以自动发生:

julia> x = 2 + 3.5
5.5

julia> typeof(x)
Float64

我们把一个Int64和一个Float64相加,得到了Float64结果。

事实上,在执行加法之前,整数已经被静默转换为Float64。

浮点数到整数转换必然更复杂。 小数点后的部分你想怎么处理?

  • round()函数会转换为最接近的整数,像 4.5 这样的中间值会舍入到最接近的_偶数_整数。
  • floor()向下取整,ceil()向上取整,trunc()向零取整。
  • 尝试直接转换,例如使用Int32(),会失败并抛出InexactError。

不过,默认情况下,这些函数不会返回你可能想要的整数类型。 可以指定所需的输出类型。

julia> round(4.5)
4.0

julia> ceil(Int, 4.3)
5

还可以使用digits关键字舍入到指定的小数位数。

julia> round(π, digits=10)
3.1415926536

除以零

这难道不是只会抛出错误吗? 事实上,情况并没有那么简单。

使用÷或//进行整数除法会如你所料导致错误。

使用/进行浮点除法时,采用的可能是工程上的做法,而不是标准的计算机科学做法:

julia> 2 / 0
Inf

julia> 0 / 0
NaN

如前文所述,无穷大在 Julia 中是一个有效的浮点数,用Inf表示。

当分子也为零时,结果在数学上是未定义的。 这时 Julia 会把它当作“非数字”,用NaN表示。

说明

你的朋友 Chandler 打算去世界各地充满异国风情的国家旅行。可惜,Chandler 的数学不太好。他非常担心旅途中被货币兑换点坑,所以想让你帮他做一个货币计算器。以下是他对这个应用的具体要求:

1. 估算兑换后的价值

创建exchange_money()函数,它接收 2 个形参:

  1. budget:你计划用于兑换的金额。
  2. exchange_rate:一单位外币相当于多少本国货币。

这个函数应返回兑换后货币的价值。

**注意:**如果你的货币是美元,想把美元按1.20的汇率兑换成欧元,那么1.20 USD == 1 EUR。

julia> exchange_money(127.5, 1.2)
106.25

2. 计算兑换后剩余的金额

创建get_change()函数,它接收 2 个形参:

  1. budget:兑换前的金额。
  2. exchanging_value:从预算中取走用于兑换的金额。

这个函数应返回预算中剩余的金额。

julia> get_change(127.5, 120)
7.5

3. 计算纸币的价值

创建get_value_of_bills()函数,它接收 2 个形参:

  1. denomination:单张纸币的面值。
  2. number_of_bills:纸币的总张数。

这个兑换点只处理特定面额单位的现金。你收到的总额必须能被一张“纸币”或一个单位的面值整除,因此可能会留下小数或余数。你的函数应只返回兑换点返还的纸币的总价值(不含小数部分)。可惜的是,兑换点会把余数/零头留作额外的奖励。

julia> get_value_of_bills(5, 128)
640

4. 计算纸币的张数

创建get_number_of_bills()函数,它接收amount和denomination。

这个函数应返回在给定的amount内你能收到的纸币张数。换句话说:起始金额能装下多少张整张纸币?记住,你只能收到整张纸币,不能收到零碎的纸币,所以记得相应地做除法。实际上,你是在向下取整到最接近的整张纸币/面值。

julia> get_number_of_bills(127.5, 5)
25

5. 计算兑换成纸币后的剩余

创建get_leftover_of_bills()函数,它接收amount和denomination。

这个函数应返回在给定纸币面值的情况下,起始amount中无法返还的剩余金额。准确知道兑换点能留下多少钱非常重要。

julia> get_leftover_of_bills(127.5, 20)
7.5

6. 计算兑换后的价值

创建exchangeable_value()函数,它接收budget、exchange_rate、spread和denomination。

形参spread是作为兑换费收取的百分比,以整数表示。需要将它除以 100 转换成小数。如果1.00 EUR == 1.20 USD,而spread为10,那么实际的总汇率将是:1.00 EUR == 1.32 USD,因为 1.20 的 10% 是 0.12,这笔额外费用会加到兑换中。

这个函数应在计算出汇率加上spread之后,返回新货币的最大价值。记住,货币的面值是整数,不能再细分。

**注意:**返回值应为整数类型。

julia> exchangeable_value(127.25, 1.20, 10, 20)
80

julia> exchangeable_value(127.25, 1.20, 10, 5)
95
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Julia Exercism

准备好开始 货币兑换 了吗?

注册 Exercism,借助 35 个概念128 个练习 和真人导师指导,学习并掌握 Julia,全部免费。