行走的数字

[复制链接]
发表于 2022-10-5 22:00:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、前言

有一定数学基础的同学们都知道,如果两个正整数相除之后得到的结果,要么能除尽,要么就是一个循环小数。
假如结果是循环小数,那么小数的每一位取值是0-9,且存在循环节点。如果我们用小数的每一位进行画图,每位小数用固定的线段表示,而每位小数的大小则用角度(1代表36度,2代表72度,以此类推)表示,这样的话我们就可以看到画图板上有一条线段在行走一样。
示例:
1/7=0.142857142857142857…
第1位小数是1,则画一条长度固定,角度为72°的线段,接着第2位小数是4,在原线段基础上画一条长度固定,角度为144°的线段,依次类推,就会形成如下图案:

只要是循环小数,最后都会形成一个对称的图形。如上图,感觉还是挺好看的。或许这就是数学之美吧~
二、准备

2.1 用到的库

decimal:高精度库,可以用来计算更高精度的小数。
turtle:大名鼎鼎的海龟画图库,用来画图。
2.2 原理介绍

1、使用高精度库计算2个数字相除之后的结果,最好精确到200位以上。
2、编写一个函数,用来求第一步结果的小数部分并做处理,求到这个小数的固定部分及循环位数。例如:1/12=0.08333333,那么固定部分就是:08,循环部分就是:3。
3、为了能用尽量少的画笔画成最终的图形(形成对称),我们需要用固定部分+循环部分*10的小数位来进行画图。
三、实例

3.1 完整代码
  1. # Encoding: utf-8
  2. # Author: 思必得
  3. # Date: 2021-09-29 14:21
  4. # Project name: FrbPythonFiles
  5. # IDE: PyCharm
  6. # File name: walknumber
  7. # 模块说明:
  8. """
  9. """
  10. # 更新日志日志:
  11. """
  12. 1、2021-09-29:
  13.     a、完成初版
  14. """
  15. # 待修改:
  16. """
  17. """
  18. def 求两个数相除之后的小数部分的循环小数(p_dividend: int, p_divisor: int, p_prec: int = 500):
  19.     """
  20.     求两个整数相除之后的小数部分的循环小数,包括4部分:固定部分 + 循环部分 + 固定部分的长度 + 循环部分的长度
  21.     比如1/7=0.142857142857142857142857142857,那么最后返回:('', '142857', 0, 6)
  22.     @param p_dividend: 被除数
  23.     @param p_divisor: 除数
  24.     @param p_prec: 小数的精确度(精确到多少位)
  25.     @return: {tuple:固定部分 + 循环部分 + 固定部分的长度 + 循环部分的长度}
  26.     @author: 思必得
  27.     @note:调用示例:
  28.     (1, 95)     ('0', '105263157894736842', 1, 18)
  29.     (1, 97)     ('', '010309278350515463917525773195876288659793814432989690721649484536082474226804123711340206185567', 0, 96)
  30.     (1, 193)    循环部分的长度:192位
  31. (1, 479)    循环部分的长度:239位
  32. (1, 384)    固定部分的长度:7位
  33.     """
  34.     from decimal import getcontext, Decimal
  35.     getcontext().prec = p_prec  # 设置精度
  36.     if p_dividend % p_divisor == 0:  # 整除的情况
  37.         return None
  38.     _shang_str = str(Decimal(p_dividend) / Decimal(p_divisor))
  39.     _index = _shang_str.find('.')
  40.     _str_digits = _shang_str[_index + 1:]
  41.     _len_digits = len(_str_digits)
  42.     if len(_shang_str) - 1 < p_prec:  # 非循环小数
  43.         return None
  44.     _half = _len_digits // 2
  45.     for i in range(_half):
  46.         for j in range(1, _half - i):
  47.             _ratio = (_len_digits - i) // j
  48.             _lt = _str_digits[slice(i)] + _str_digits[slice(i, i + j)] * _ratio
  49.             _lt = _lt + _str_digits[slice(i, i + j)][slice(_len_digits - len(_lt))]
  50.             if _lt[:-1] == _str_digits[:-1]:
  51.                 _fix = _str_digits[slice(0, i)]
  52.                 _loop = _str_digits[slice(i, i + j)]
  53.                 return _fix, _loop, len(_fix), len(_loop)
  54. if __name__ == '__main__':
  55.     import turtle as tt
  56.     if s := 求两个数相除之后的小数部分的循环小数(1, 13):
  57.         ss = s[0] + s[1] * 10
  58.         print(s)
  59.         print(ss, len(ss))
  60.         tt.setup(width=1.0, height=1.0)
  61.         pen = tt.Pen()
  62.         for i in ss:
  63.             pen.left(int(i) * 36)
  64.             pen.forward(100)
  65.         tt.exitonclick()
  66.     else:
  67.         print('无法作图,结果不是循环小数')
复制代码
3.2 一些结果

3.2.1 1/11

('', '09', 0, 2)

3.2.2 1/13

('', '076923', 0, 6)

3.2.3 1/17

('', '0588235294117647', 0, 16)

3.2.4 1/19

('', '052631578947368421', 0, 18)

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表