python分数约分_C++、Java、Python中都是怎么精确表达分数的?

你要的东西,STL 库已经有了,叫 std::ratio ,是 C++11 标准的模板类。在 C++11 标准之后,C++委员会加入了大量高等数学相关的函数,beta函数、gamma函数、黎曼Zeta函数、球面贝塞尔函数等等,少不了优秀的先驱库 boost 的功劳。Standard library header ​en.cppreference.com

std::ratio_add、std::ratio_subtract、std::ratio_multiply、ratio_divide 对应加减乘除四则运算,然后分数间比较大小的函数也有。下面用 std::ratio 来做一下加减乘除运算:

#include #include

int main()

{

using two_third = std::ratio<2, 3>;

using one_sixth = std::ratio<1, 6>;

using sum = std::ratio_add;

std::cout << "2/3 + 1/6 = " << sum::num << '/' << sum::den << '\n';

using diff = std::ratio_subtract;

std::cout << "2/3 - 1/6 = " << diff::num << '/' << diff::den << '\n';

using product = std::ratio_multiply;

std::cout << "2/3 * 1/6 = " << product::num << '/' << product::den << '\n';

using quotient = std::ratio_divide;

std::cout << "(2/3) / (1/6) = " << quotient::num << '/' << quotient::den << '\n';

return 0;

}

程序输出结果:

2/3 + 1/6 = 5/6

2/3 - 1/6 = 1/2

2/3 * 1/6 = 1/9

(2/3) / (1/6) = 4/1

如果初学,不妨自己尝试写个分数类;如果在工程项目里,就用标准库里的东西。有人反馈上面是模板元编程(Template Metaprogramming),不是类,你可以自己写一个分数类,然后重载加减乘除、大小比较等操作符。然后需要熟悉一个算法,小学里的通分求最小公倍数(least common multiple),分数化简求最大公约数(greatest common divisor)。求 gcd 的算法是辗转相除法,然后根据恒等式 gcd(a, b) * lcm(a, b) = a * b,求得 lcm,希望你自己也能手写出代码。当然,这两个函数在 C++ 库里也是有的,用的首字母缩写,分别对应std::lcm、std::gcd。代码可以参考 boost::rational,C++没有把这个类集成进来成,即没有 std::rational。

编程中你会遇到的问题:std::gcd 是 C++17引入的,自己实现的话算法用递归,还是非递归实现?(小问题);

模板限制类型为有符号整形,无符号整形需要额外的数据来表示正负(C++11用static_assert,C++20可以用 requires 来限制类型);

除以值为0的分数如何处理?(根据个人需求决定是否抛异常,抛异常就不用处理特殊的数);

通分后分母表示的整数过大导致溢出了如何处理?(能约分则尽量约分)。

详细的 C++ 代码可以参考这里。为了增加健壮型,这里处理了 +0, -0, +∞, -∞, NaN这5个特殊的数,让它们符合浮点数的运算规则

0 * inf 等于 nan

0 / inf 等于 0

inf * inf 等于 inf

negative_finite_rational * +inf 等于 -inf

inf - inf 等于 nan

nan == nan 返回 false

inf == inf 返回 true

inf < inf 返回 false

另,提一下培养编程修养——英语也要抓。我见过初学者写阶乘的代码用拼音命名函数名。考虑到所有的有理数可以用分数表示,类名用有理数(Rational)还是分数(Fraction)都行,数据成员有分子(numerator),分母( denominator)。不要偷懒用a和b表示,一眼看去不知道谁是分子,谁是分母。Rational Number Library - 1.55.0​www.boost.org

题目有所更改,新添加了 Java 和 Python 语言,那我也补充一下回答好了。算法都是一样的,只是用不同的语言描述而已。代码都是用英语写的。

Java 是直接支持大整数(java.math.BigInteger)和大浮点数(java.math.BigDecimal)的运算,没有直接的Rational类。BigInteger 里也提供了gcd 和 lcm 方法。

Android 的上层用 Java 语言写的,有 android.util.Rational 类表示有理数,实现了 Comparable 接口,里面有常用的静态常量0, +∞, -∞, NAN。代码有bug。有NaN参与比较的话总是失败,即应该返回false。注释“NaN is greater than the other non-NaN value”、“the other NaN is greater than this non-NaN value”是错误的。

Python 有 fractions 类,支持字符串、分子+分母构造有理数,比较丰富。比如你可以传递字符串'1/3',它就表示1/3了。可以看别人的代码学习,传送门。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值