Python_进阶_浮点型(float)不可避免的误差产生原因,float类型在所有计算机中的储存方式——获得图灵奖的天才设计:IEEE754 标准

Python_进阶_浮点型(float)不可避免的误差产生原因,float类型在所有计算机中的储存方式——获得图灵奖的天才设计:IEEE754 标准

目录

说明

一、前言

二、理论

2.1 Bug

2.2 十进制小数转换为二进制小数

2.3 IEEE754标准

2.4 IEEE754标准实际储存的格式

2.4.1 通用情况

2.4.2 特殊情况

2.4.3 规格化浮点数与非规格化浮点数

2.4.4 通用储存格式

2.5 二进制舍入原理

三、计算结果验证

3.1 验证

3.2 误差消除方法

四、整体代码及注释

五、结语

五、参考


说明

本文仅作为学习分享

本文在描述IEEE754 标准时,仅描述了双精度浮点型(64位)的情况。但单精度浮点型与其理论相同,所以不再赘述。

关键词:

IEEE754标准;Float;Python;二进制舍入

一、前言

在学习计算机语言时,经常会遇到一个很经典的BUG——计算机在计算小数时一定会产生误差,特别是在科学计算时。

本科时的老师就让我们有兴趣的话课下可以学习一下这方面的知识,但当时仅仅只是浅显的了解了一下。直到这两天才深入学习了这方面的知识。

本来我以为这是一个很小的知识点,但学习之后才发现这是一个非常重要的系统化的知识。

深入学习非常有助于理解计算机和计算机语言,也会对软件和硬件的关系有更深刻的认识。

IEEE754 标准是获得图灵奖的天才设计,本文将较为详细的描述这个浮点数处理的基石。

二、理论

2.1 Bug

在python3.0中,如果我们直接将两个小数相加,大概率是个错误结果

图2-1 BUG例程
图2-1 BUG例程

0.1+0.2的结果明明是0.3,可是计算机却出现了这种显而易见的低级错误

这明显是错误的,可是是什么导致了这个错误呢?

我们大致需要以下知识:

1:十进制小数转换为二进制

2:IEEE754标准

3:二进制舍入方法

2.2 十进制小数转换为二进制小数

十进制小数转换为二进制小数的方法是——整数部分展除二取余并逆位读数,小数部分乘二取整并顺位读数。

这方面知识不会的请去查阅,在此不再赘述。

例如3.5这个小数

计算结果为整数部分11,小数部分1。所以整体为:0b11.1

现在验证一下

图2-2 验证进制转换

结果正确

2.3 IEEE754标准

现在简单介绍一下电气电子工程师学会(IEEE)754浮点数储存标准

IEEE 754是计算机中表示浮点数的通用标准,定义了二进制浮点数的格式、精度、舍入规则及异常处理方式。该标准广泛应用于硬件和软件实现,确保浮点数运算的跨平台一致性。

IEEE754标准可以表达为:(-1)^Sign * Base^Exponent  * Mantissa

其中“*”为乘号
其中“^”为指数符号 (在python中为“**”)
其中Sign为正负标志
其中Mantissa为尾数,或者说有效数值,这个数值必须且仅保留一位正数位
其中Base为基数,或者说进制
其中Exponent为指数,或者说小数进位数

此标准适用于所有浮点数,包括软件和硬件

看不懂没关系,下面会举例

2.4 IEEE754标准实际储存的格式

上文的表达式是IEEE754标准的表达式,但和实际储存方式有细微的差别

2.4.1 通用情况

        Sign符号位很简单,正数为0,负数为一
        Base更简单,这是在确定进制之后的固定值,计算机储存一般为2
        Mantissa也很简单,将有效数值小数点后的数值储存就行,因为规格化浮点数的小数正数部分一定为一(规格化浮点数后面解释)
        但在储存Exponent时有一个问题,如果指数是负数,那么需要一个额外的符号位去表示指数的正负
在python中,也就是双精度浮点型标准下,实际指数储存时会加上11位指数位最大值的一半,也就是储存的Exponent_input=Exponent+1023
我们将这个指数位最大值的一半1023称之为偏移量
通过加上这个偏移量,可以直接使得储存的所有指数的值皆大于等于零,不需要额外的符号位
那么显而易见的是,理论上11位指数位0-2047可以表示-1023—+1024这2048个指数值

2.4.2 特殊情况

IEEE754标准规定浮点数在储存指数时保留两种特殊情况

1:指数部分全为1时
        若尾数部分为零,则此时表示无穷大
                且若符号位为1时,则表示负无穷大
                且若符号位为0时,则表示正无穷大
        若尾数部分不为零,则表示NaN(Not a Number),即无效数字
2:指数部分全为零时,表示这是一个非规格化浮点数

2.4.3 规格化浮点数与非规格化浮点数

我们先来解释什么是规格化浮点数

python在储存尾数时,直接舍弃了整数部分的一位,因为正常情况下浮点数二进制储存的正数位一定是1,所以我们可以节省下这一位的空间

在这种正数位为1的情况下的浮点数,我们称之为规格化浮点数

规格化浮点数在计算原始指数时,只需要将储存值减去偏移量,即Exponent=Exponent_input-1023

但在非规格化浮点数的情况下,也就是指数为零时,尾数舍弃的正数部分变为了0

这时的原始指数Exponent=Exponent_input-1023这个公式不再适用,因为非规格化浮点数的正数部分不合规格,即无有效的正数部分

此时,原始指数Exponent=1-1023,恒等于-1022
此时,又会出现特殊情况,即尾数为0
IEEE754标准规定:当指数为零,尾数为零时,值为0
且当符号为正时,表示0+
且当符号为负时,表示0-

可是,为什么要这么做呢?这不是看起来多此一举吗?

其实答案就在默认隐含掉的正数部分上

如果我们不引入非规格化浮点数,那么就默认尾数的正数部分为1

此时最小数为1.0*2**(-1022)

也就是说此时,我们虽然指数的数量级最小了,但尾数完全不是最小数量级

我们浪费掉了52位尾数位的数量级

但如果引入非规格化浮点数之后,隐含掉的正数部分变为了0

于是此时我们可以完全利用尾数的52位

此时的最小数为2**(-52)*2**(-1022),整整差了52个数量级

通过上述的内容,我们也能得出一个结论,双精度浮点数的精度为2**(-1074)

2.4.4 通用储存格式

经过上文的论述,我们已经对python双精度浮点数的储存模式有了清晰的概念

本文只描述规格化浮点数的情况,但其实非规格化浮点数,0,无穷大和NaN原理相同,读者可以自行推导。

python中以二进制储存(或者说绝大部分的计算机语言都用二进制储存),那么基数是确定的,也就是2。
而python舍弃了整数部分的1位,所以实际的尾数为Mantissa-1,仅保留小数部分
对于规格化浮点数,Exponent_input=Exponent+1023
所以python的浮点数表达式为:(-1)**Sign * Mantissa * (2**Exponent)
实际储存时,从高到低的数据格式为:sign[0]Exponent[10:0]Mantissa[51:0]
实际储存时,从高到低的实际数据为:[sign][Exponent+1023][Mantissa-1]

说起来有点复杂,但其实很简单,现在我举个例子

例如上文中的小数3.5,二进制为:0b11.1

首先它是个正数,那么S为0

有效值的进位为1,所以Exponent为1+1023=1024,1024转换为二进制为100 0000 0000

它的有效数值为1.11,那么Mantissa=1.11,我们只取小数点后的有效数值11

将他们拼接起来,所以小数3.5在python中实际储存为:

0_10000000000_1100000000000000000000000000000000000000000000000000

现在我们验证一下

图2-3 3.5实际储存验证

计算与结果完全一致

2.5 二进制舍入原理

现在我们回到最开始的问题,为什么会出现那个Bug

实际上,除了小数点后最后一位为5的所有小数,在计算机中都并不精准

从我们刚刚学习的浮点数储存方式中,我们知道小数部分是用乘二取整法转换的

那么python中储存0.1的实际数据是什么呢?

理论上,0.1转换为二进制为0.0001100110011....0011

这是一个无限循环

根据上文的推导,可以简单得出sign=0,exponent=-4

故exponent_input=-4+1023=1019,转换为二进制为001111111011

mantissa=1.100110011....0011,舍去正数位为100110011....0011

故整体储存为:0_001111111011_100110011....

但是我们知道,我们只有52位尾数位,所以必然不是精确数值

在python3.0中,float储存遵循的是IEEE754标准中的“最近舍入,平局则偶”

意思是尾数的舍入选取离实际数值最近的那个数值,如果有两个数值离实际数值一样近,则选择偶数数值(十进制下的最后一位)

但是如何在计算机的二进制中实现这个目标呢?

接下来我将介绍另一个天才设计—二进制“最近舍入,平局则偶”舍入方法

这个方法需要三个标志位:

保护位(Guard bit, G):紧跟在有效数字最低位之后的第一位。
舍入位(Round bit, R):保护位之后的第二位。
粘滞位(Sticky bit, S):舍入位之后的所有剩余位经过逻辑或运算得到的一个标志位(只要剩余位中有1,S就为1;全为0则S为0)

通过 G、R、S 三个位的组合,可以准确判断中间结果与两个最近可表示浮点数的距离关系

情况一:G=0
则说明靠近较小的数,向下舍入
情况二:G=1 且 (R或S=1)
则说明靠近较大的数,向上舍入
情况三:G=1 且 R=0 且 S=0
平局
舍入结果:根据目标有效数字的最低位(LSB)决定:
如果 LSB = 0(偶数),则向下舍入(保持最低位为 0);
如果 LSB = 1(奇数),则向上舍入(使最低位变为 0,因为加 1 后最低位变为 0,可能进位到更高位)

我们可以简单得出,0.1的最后一字节数据为1001,后续数据为:1001001001....

故G=1,R=0,S=1

那么根据以上原则,应向上舍入,即将1001舍入为1010

所以,整体数据为:
0_01111111011_1001100110011001100110011001100110011001100110011010

三、计算结果验证

3.1 验证

我们先验证一下0.1的计算推导结果

图3-1 0.1实际储存验证

计算与结果完全相等

经过计算,这个数值实际为

0.1000000000000000055511151231257827021181583404541015625

同理可得,0.3在储存中的实际数值为

0.200000000000000011102230246251565404236316680908203125

在python中将这两个数值相加

图3-2 和验证

与预期一致

3.2 误差消除方法

想要消除这种误差,实际使用python等计算机语言时有很多方法可以做到

这些方法都极其简单,比如decimal模块、fractions模块、使用整数运算(缩放法)、比较时使用容差(math.isclose)、格式化输出时控制小数位数等

在此不再赘述

当然,这也是一个很好的课题

四、整体代码及注释

#接下来我们看一个非常经典的计算机蝽(Bug) float_num_error=0.1+0.2 print(float_num_error) #输出结果为0.30000000000000004 #这明显是错误的,可是是什么导致了这个错误呢? #我们需要以下知识: #1:十进制整数即小数部分转换为二进制 #2:IEEE754双精度浮点数(64位)储存标准 #首先我们先解释十进制小数转换为二进制小数 #十进制小数转换为二进制小数的方法是——整数部分展除二取余并逆位读数,小数部分乘二取整并顺位读数 #这方面知识不会的请去查阅,在此不再赘述 #例如3.5 #计算结果为整数部分11,小数部分1。所以整体为:0b11.1 #现在验证一下 float_num=0b11+0b1/(1<<1)#python无法直接表达二进制小数,故采用组合方式,新手不用管 print(float_num) #结果正确 #现在简单解释一下电气电子工程师学会(IEEE)754双精度浮点数(64位)储存标准 #IEEE754标准可以表达为:(-1)**Sign * Mantissa * Base**Exponent #其中“*”为乘号 #其中“**”为指数符号 #其中Sign为正负标志 #其中Mantissa为尾数,或者说有效数值,这个数值必须且仅保留一位正数位 #其中Base为基数,或者说进制 #其中Exponent为指数,或者说小数进位数 #现在的问题是,python等计算机实际储存的格式 #Sign符号位很简单,正数为0,负数为一 #Base更简单,这是在确定进制之后的固定值,计算机储存一般为2 #Mantissa也很简单,将有效数值小数点后的数值储存就行 #但在储存Exponent时有一个问题,如果指数是负数,那么需要一个额外的符号位去表示指数的正负 #在python中,实际指数储存时会加上11位指数位最大值的一半,也就是储存的Exponent_input=Exponent+1023 #我们将这个指数位最大值的一半1023称之为偏移量 #通过加上这个偏移量,可以直接使得储存的所有指数的值皆大于等于零,不需要额外的符号位 #那么显而易见的是,理论上11位指数位0-2047可以表示-1023—+1024这2048个指数值 #但是IEEE754标准规定浮点数在储存指数时保留两种特殊情况 #1:指数部分全为1时 #若尾数部分为零,则此时表示无穷大 #且若符号位为1时,则表示负无穷大 #且若符号位为0时,则表示正无穷大 #若尾数部分不为零,则表示NaN(Not a Number),即无效数字 #2:指数部分全为零时,表示这是一个非规格化浮点数 #我们先来解释什么是规格化浮点数 #python在储存尾数时,直接舍弃了整数部分的一位,因为正常的浮点数二进制储存的正数位一定是1,所以我们可以节省下这一位的空间 #在这种正数位为1的情况下的浮点数,我们称之为规格化浮点数 #规格化浮点数在计算原始指数时,只需要将储存值减去偏移量,即Exponent=Exponent_input-1023 #但当指数为零时,尾数舍弃的正数部分变为了0 #这时的原始指数Exponent=Exponent_input-1023这个公式不再适用,因为非规格化浮点数的正数部分不合规格,即无有效的正数部分 #此时,原始指数Exponent=1-1023,恒等于-1022 #此时,又会出现特殊情况,即尾数为0 #IEEE754标准规定:当指数为零,尾数为零时,值为0 #且当符号为正时,表示0+ #当符号为负时,表示0- #为什么要引入非规格化浮点数?其实答案就在隐含掉的正数部分上 #如果我们不引入非规格化浮点数,那么就默认尾数的正数部分为1 #此时最小数为1.0*2**(-1022) #也就是说此时,我们虽然指数的数量级最小了,但尾数完全不是最小数量级 #我们浪费掉了52位尾数位的数量级 #但如果引入非规格化浮点数之后,隐含掉的正数部分变为了0 #于是此时我们可以完全利用尾数的52位 #此时的最小数为2**(-52)*2**(-1022) #整整差了52个数量级 #通过上述的内容,我们也能得出一个结论,双精度浮点数的精度为2**(-1074) #经过上文的论述,我们已经对python双精度浮点数的储存模式有了清晰的概念 #python中以二进制储存(或者说绝大部分的计算机语言都用二进制储存),那么基数是确定的,也就是2。 #而python舍弃了整数部分的1位,所以实际的尾数为Mantissa-1 #在此本文只描述规格化浮点数的情况 #对于规格化浮点数,Exponent_input=Exponent+1023 #所以python的浮点数表达式为:(-1)**Sign * Mantissa * (2**Exponent) #实际储存时,从高到低的数据格式为:sign[0]Exponent[10:0]Mantissa[51:0] #实际储存时,从高到低的实际数据为:[sign][Exponent+1023][Mantissa-1] #说起来很复杂,但其实很简单,现在我举个例子 #例如上文中的小数3.5,二进制为:0b11.1 #首先它是个正数,那么S为0 #它的有效数值为1.11,那么Mantissa=1.11,且Mantissa-1=0.11,我们只取小数点后的有效数值11 #它的进位为1,所以Exponent为1+1023=1024,1024转换为二进制为100 0000 0000 #将他们拼接起来,所以小数3.5在python中实际储存为:0_10000000000_1100000000000000000000000000000000000000000000000000 #现在我们验证一下 import struct def float_to_binary64(f): #将浮点数打包为8字节(默认使用本机字节序,通常为小端) bytes_=struct.pack('d',f) #将每个字节转换为8位二进制并拼接并转换为大端序.join(f'{b:08b}' for b in struct.pack('>d', f)) return bits f = 3.5 #将任何你想测试的值填入f bits = float_to_binary64(f) print(bits) #计算与结果完全一致 #现在我们回到最开始的问题,为什么会出现那个Bug #实际上,除了小数点后最后一位为5的所有小数,在计算机中都并不精准 #从我们刚刚学习的浮点数储存方式中,我们知道小数部分是用乘二取整法转换的 #那么python中储存0.1的实际数据是什么呢? #理论上,0.1转换为二进制为0.0001100110011....0011 #这是一个无限循环 #根据上文的推导,可以简单得出sign=0,exponent=-4 #故exponent_input=-4+1023=1019,转换为二进制为001111111011 #mantissa=1.100110011....0011,舍去正数位为100110011....0011 #故整体储存为:0_001111111011_100110011.... #但是我们知道,我们只有52位尾数位,所以必然不是精确数值 #在python3.0中,float储存遵循的是IEEE754标准中的“最近舍入,平局则偶” #意思是尾数的舍入选取离实际数值最近的那个数值,如果有两个数值离实际数值一样近,则选择偶数数值(十进制下的最后一位) #但是如何在计算机的二进制中实现这个目标呢? #接下来我将介绍另一个天才设计—二进制“最近舍入,平局则偶”舍入方法 #这个方法需要三个标志位: #保护位(Guard bit, G):紧跟在有效数字最低位之后的第一位。 #舍入位(Round bit, R):保护位之后的第二位。 #粘滞位(Sticky bit, S):舍入位之后的所有剩余位经过逻辑或运算得到的一个标志位(只要剩余位中有1,S就为1;全为0则S为0)。 #通过 G、R、S 三个位的组合,可以准确判断中间结果与两个最近可表示浮点数的距离关系 #情况一:G=0 #则说明靠近较小的数,向下舍入 #情况二:G=1 且 (R或S=1) #则说明靠近较大的数,向上舍入 #情况三:G=1 且 R=0 且 S=0 #平局 #舍入结果:根据目标有效数字的最低位(LSB)决定: #如果 LSB = 0(偶数),则向下舍入(保持最低位为 0); #如果 LSB = 1(奇数),则向上舍入(使最低位变为 0,因为加 1 后最低位变为 0,可能进位到更高位)。 #我们可以简单得出,0.1的最后一字节数据为1001,后续数据为:1001001001.... #故G=1,R=0,S=1 #那么根据以上原则,应向上舍入,即将1001舍入为1010 #所以,整体数据为——0_01111111011_1001100110011001100110011001100110011001100110011010 #验证 import struct def float_to_binary64(f): #将浮点数打包为8字节(默认使用本机字节序,通常为小端) bytes_=struct.pack('d',f) #将每个字节转换为8位二进制并拼接并转换为大端序.join(f'{b:08b}' for b in struct.pack('>d', f)) return bits f = 0.1 #将任何你想测试的值填入f bits = float_to_binary64(f) print(bits) #计算与结果完全相等 #经过计算,这个数值实际为0.1000000000000000055511151231257827021181583404541015625 #同理可得,0.3在储存中的实际数值为0.200000000000000011102230246251565404236316680908203125 #将这两个数值相加 float_num=0.1000000000000000055511151231257827021181583404541015625+0.200000000000000011102230246251565404236316680908203125 print(float_num) #与预期一致 #想要消除这种误差,有很多方法可以做到 #这些方法都极其简单,比如decimal模块、fractions模块、使用整数运算(缩放法)、比较时使用容差(math.isclose)、格式化输出时控制小数位数等 #在此不再赘述 #但最重要的是,要理解这种误差,并且平衡效能(速度)和误差之间的关系。有的时候,没有必要为了无效的精准度而牺牲效率

五、结语

IEEE754标准,这个浮点数的基石,我认为诠释了电子数学的美。

电子数学与数学的区别是,我们不得不面对物理、器件、技术、材料等的限制。电子技术没有最好,只有更好

我们必须在精度、范围和效率之间找到一个平衡点

就像生活一样不是吗?

本躯能力不足,若有错误恳请斧正

五、参考

  1.  C语言中文网 n.d., '小数在内存中是如何存储的,揭秘诺贝尔奖级别的设计(长篇神文)', C语言中文网, viewed 28 February 2026, http://c.biancheng.net/
  2.  ZEEKLOG博客 2024, '控制python中的浮点精度', 腾讯云开发者社区, viewed 28 February 2026, https://cloud.tencent.cn/developer/information/控制python中的浮点精度
  3.  Oracle Corporation 2016, Numerical Computation Guide, part number E71940-01, Oracle Developer Studio 12.5, viewed 28 February 2026, https://docs.oracle.com/cd/E71940_01/html/E71991/z4000ac019878.html
  4. Stack Overflow 2014, 'Python3 rounding to nearest even', Stack Overflow, viewed 28 February 2026, https://stackoverflow.com/questions/23248489
  5. 科普中国 2019, '双精度浮点数', 科普中国·科学百科, viewed 28 February 2026, https://cloud.kepuchina.cn/newSearch/imgText?from=1&id=6974140214012293121

Read more

DeepSeek-R1是真码农福音?我们问了100位开发者……

DeepSeek-R1是真码农福音?我们问了100位开发者……

从GitHub Copilot到DeepSeek-R1,AI编程工具正在引发一场"效率革命",开发者们对这些工具的期待与质疑并存。据Gartner预测,到2028年,将有75%的企业软件工程师使用AI代码助手。 眼看着今年国产选手DeepSeek-R1凭借“深度思考”能力杀入战场,它究竟是真码农福音还是需要打补丁的"潜力股"? ZEEKLOG问卷调研了社区内来自全栈开发、算法工程师、数据工程师、前端、后端等多个技术方向的100位开发者(截止到2月25日),聚焦DeepSeek-R1的代码生成效果、编写效率、语法支持、IDE集成、复杂代码处理等多个维度,一探DeepSeek-R1的开发提效能力。 代码生成效果:有成效但仍需提升 * 代码匹配比例差强人意 在代码生成与实际需求的匹配方面,大部分开发者(58人)遇到生成代码与实际需求完全匹配无需修改的比例在40%-70%区间,12人遇到代码匹配比例在70%-100%这样较高的区间。 然而,有30人代码匹配比例低于40%。这说明DeepSeek-R1在代码生成方面有一定效果,但在部分复杂或特定场景下,仍有很大的提升空间。

By Ne0inhk
在 VSCode 中本地运行 DeepSeek,打造强大的私人 AI

在 VSCode 中本地运行 DeepSeek,打造强大的私人 AI

本文将分步向您展示如何在本地安装和运行 DeepSeek、使用 CodeGPT 对其进行配置以及开始利用 AI 来增强您的软件开发工作流程,所有这些都无需依赖基于云的服务。  步骤 1:在 VSCode 中安装 Ollama 和 CodeGPT         要在本地运行 DeepSeek,我们首先需要安装Ollama,它允许我们在我们的机器上运行 LLM,以及CodeGPT,它是集成这些模型以提供编码辅助的 VSCode 扩展。 安装 Ollama Ollama 是一个轻量级平台,可以轻松运行本地 LLM。 下载Ollama 访问官方网站:https://ollama.com * 下载适合您的操作系统(Windows、macOS 或 Linux)的安装程序。 * 验证安装 安装后,打开终端并运行: ollama --version  如果 Ollama 安装正确,

By Ne0inhk
AI+游戏开发:如何用 DeepSeek 打造高性能贪吃蛇游戏

AI+游戏开发:如何用 DeepSeek 打造高性能贪吃蛇游戏

文章目录 * 一、技术选型与准备 * 1.1 传统开发 vs AI生成 * 1.2 环境搭建与工具选择 * 1.3 DeepSeek API 初步体验 * 二、贪吃蛇游戏基础实现 * 2.1 游戏结构设计 * 2.2 初始化游戏 * 2.3 DeepSeek 生成核心逻辑 * 三、游戏功能扩展 * 3.1 多人联机模式 * 3.2 游戏难度动态调整 * 3.3 游戏本地保存与回放 * 3.4 跨平台移植 * 《Vue.js项目开发全程实录/软件项目开发全程实录》 * 编辑推荐 * 内容简介 * 作者简介 * 目录 一、

By Ne0inhk
[DeepSeek] 入门详细指南(上)

[DeepSeek] 入门详细指南(上)

前言 今天的是 zty 写DeepSeek的第1篇文章,这个系列我也不知道能更多久,大约是一周一更吧,然后跟C++的知识详解换着更。 来冲个100赞兄弟们 最近啊,浙江出现了一匹AI界的黑马——DeepSeek。这个名字可能对很多人来说还比较陌生,但它已经在全球范围内引发了巨大的关注,甚至让一些科技巨头感到了压力。简单来说这 DeepSeek足以改变世界格局                                                   先   赞   后   看    养   成   习   惯  众所周知,一篇文章需要一个头图                                                   先   赞   后   看    养   成   习   惯   上面那行字怎么读呢,让大家来跟我一起读一遍吧,先~赞~后~看~养~成~习~惯~ 想要 DeepSeek从入门到精通.pdf 文件的加这个企鹅群:953793685(

By Ne0inhk