Python float 和 decimal

作者: 叫我老村长 | 来源:发表于2019-12-17 11:12 被阅读0次

Python float 和 decimal

这里我想记录的是 Python 的 Decimal 类型和 float 的转换问题。

Python 的 Decimal 支持从 str 和 float 进行转换,比如

from decimal import Decimal

f = 3.1666666666666666
Decimal(str(f))
Decimal('3.16666666667')
Decimal(f)
Decimal('3.166666666666666518636930049979127943515777587890625')
Decimal.from_float(f)
Decimal('3.166666666666666518636930049979127943515777587890625')

比如很明显能看出一个数通过 str 或 float 直接转换都会和真正输入的不一样,这个问题是由于小数以二进制形式在计算机内表达的问题。除此之外,可以很明显看到 float 转换到 str 是经过 round 的,具体可以参考 converting-a-float-to-a-string-without-rounding-it ,最终说的都是浮点用二进制表示的问题。

所以在应对精度非常高的浮点的时候,记得一定要保留指定位的小数,尤其是在数据库设计时如果需要 Decimal 类型的,记得指定具体的精度来使数据在数据库和 Python 中都能保持一致。

MySQL设计浮点类型的字段用decimal的好处与坏处

在后端开发中,数据库MySQL我以前经常使用float和double来存储浮点型数据,但现在发现很多的精度丢失问题。

现在来看看他们的区别

  • float 类型用于表示单精度浮点数值,而double类型用于表示双精度浮点数值,float 和 double 都是浮点型,而decimal 是定点型;

  • MySQL 浮点型和定点型可以用类型名称后加(M,D)来表示,M表示该值的总共长度,D表示小数点后面的长度,M和D又称为精度和标度,如float(7,4)的 可显示为-999.9999,MySQL保存值时进行四舍五入,如果插入999.00009,则结果为999.0001。

  • FLOAT 和 DOUBLE 在不指 定精度时,默认会按照实际的精度来显示,而 DECIMAL 在不指定精度时,默认整数为10,小数为0。

  • DECIMAL和NUMERIC值作为字符串存储,而不是作为二进制浮点数,以便保存那些值的小数精度

decimal的格式:decimal(M,D)中D代表存储的小数位的长度,而M代表的是整数位加小数位的总长度

看看区别

建立一张表,存着三种不同的浮点型字段,各自插入相同的数据1234567.23

image

insert INTO fudianxing VALUE (1234567.23,1234567.23,1234567.23);

image

很明显float会出错,而double和decimal在这里没错误,decimal类型在更大的范围内的精度肯定会比double高。

那就来修改表结构,插入更大的值。

image

insert INTO fudianxing VALUE (1234567.23,12345671111111111111111.23,12345671111111111111111.23);

image

这里看出decimal类型更加的好用了吧,所以大家搞起来。

先总结几个好处和缺点

float和double都是采用二进制的格式存储的,decimal在存储时采用字符串存储,能够很好地保留小数地精度。

但缺点是向decimal类型字段插入超过定义的数字会省略后几位的数字,并输出警告:(数据库版本为10.1.37-MariaDB)

比如decimal(5,2),插入222.22时是正常的;插入222.222时则省略最后一位,插入222.22;插入222.225时,就会四舍五入插入222.23;

如上定义,当插入一个四位数4396的数字时就会插入一个最大值999.99,并输出警告,不会报错;

当插入整数888时就会显示888,并不会显示888.00,这就比其他两个浮点型好。

如上是decimal的定义,我觉得是一个缺点吧,因为他们居然都插入成功了,并且以边界值来处理,但严格意义上来说并不算缺点,算是一个对错误的兼容。

现在就来说优点:

  1. 数值以字符串的形式保存,存储了一个准确(精确)的数字表达法,不存储值的近似值。
    这种方法很好地处理float和double类型都会发生的错误,因为他们都是以二进制存储的,所以有一定的误差。一个字符用于值的每一位、小数点

  2. decimal有更多的位数保存数值

    float:浮点型,含字节数为4,32bit,数值范围为-3.4E38~3.4E38(7个有效位)

    double:双精度实型,含字节数为8,64bit数值范围-1.7E308~1.7E308(15个有效位)

    decimal:数字型,128bit,不存在精度损失,常用于银行帐目计算。(28个有效位)
    decimal(a,b)

    参数说明

    a指定指定小数点左边和右边可以存储的十进制数字的最大个数,最大精度38。
    b指定小数点右边可以存储的十进制数字的最大个数。小数位数必须是从 0 到 a之间的值。默认小数位数是 0。

  3. decimal 数据类型最多可存储 38 个数字,所有数字都能够放到小数点的右边。

总结:数值用decimal就对了,因为数字迟早会变大的。

相关文章

网友评论

    本文标题:Python float 和 decimal

    本文链接:https://www.haomeiwen.com/subject/qbfjgctx.html