使用MySQL和SQLAlchemy ORM进行高精度计算

14
我使用SQLAlchemy的ORM在MySQL中存储一些数字。当我之后取回它们时,它们被截断,只保留了6个有效数字,因此失去了很多浮点数的精度。我想这应该有一个简单的解决方法,但我找不到如何解决。例如,以下代码:
import sqlalchemy as sa
from sqlalchemy.pool import QueuePool
import sqlalchemy.ext.declarative as sad

Base    = sad.declarative_base()
Session = sa.orm.scoped_session(sa.orm.sessionmaker())

class Test(Base): 
    __tablename__   = "test"
    __table_args__  = {'mysql_engine':'InnoDB'}
    no      = sa.Column(sa.Integer, primary_key=True)
    x       = sa.Column(sa.Float)


a = 43210.123456789
b = 43210.0
print a, b, a - b

dbEngine = sa.create_engine("mysql://chore:BlockWork33!@localhost", poolclass=QueuePool, pool_size=20,  
                                 pool_timeout=180)              
Session.configure(bind=dbEngine)   
session = Session()            

dbEngine.execute("CREATE DATABASE IF NOT EXISTS test")
dbEngine.execute("USE test")  
Base.metadata.create_all(dbEngine)   

try:
    session.add_all([Test(x=a), Test(x=b)])
    session.commit()
except:
    session.rollback()
    raise

[(a,), (b,)] = session.query(Test.x).all()
print a, b, a - b

生产

43210.1234568 43210.0 0.123456788999
43210.1 43210.0 0.0999999999985

我需要一个解决方案来实现它

43210.1234568 43210.0 0.123456788999
43210.1234568 43210.0 0.123456788999

1
我没有使用过SQLAlchemy,所以不确定,但根据文档,我认为你应该能够指定sa.types.Float(precision=[此处的精度])而不是sa.Float。 - AMacK
1
@AMacK 是的,我知道。我试过了……或者至少我以为我试过了。实际上,我尝试了sa.Float(Precision=32),但没有任何变化。然而,使用sa.types.Float(precision=32),它确实有效……我猜这也是SQLAlchemy名称中有“Alchemy”的原因之一。如果你把它写成答案(而不是评论),我会把它作为正式答案。 - Christian O'Reilly
非常感谢。 嗯,奇怪。好玩的时光。 - AMacK
1个回答

9

根据我们在评论中的讨论:sa.types.Float(precision=[这里填写精度]) 可以用来指定精度,而不是使用 sa.Float;但是,sa.Float(Precision=32) 没有任何效果。更多信息请参见文档


5
就我个人而言,我在处理SQLAlchemy语法时遇到了困难。我的项目使用Flask(因此使用Flask SQLAlchemy)。以下是使float在这里生效的语法:ColumnName=db.Column(db.Float(precision='3,2')) # db是Flask操作的一部分上述的“3,2”会生成一个(MySQL)字段XXX.YY。希望这对那些文档不够清晰(Flask和SQLAlchemy)的人有所帮助。 - Marc
你能引用文档或更具体地指出在哪里说 sa.Float(Precision=32) 格式没有效果吗? - Brian Peterson
@datamafia或其他人,如果您使用alembic,您是否在迁移中看到浮点精度的更改?如果是这样,它是什么样子的? - Brian Peterson
@BrianPeterson 有两件事。1-,这是我迁移的副本sa.Column('ProductPrice', sa.Float(precision='3,2'), nullable=True),。2-所有的alembic迁移都必须仔细检查,通常都会出现错误。所以引用的这行代码是可以工作的,但我可能不得不像大多数Alembic迁移一样从头开始编写它。如需更多信息,请随时直接联系我。在这个例子中,我使用的是MySQL。 - Marc
3
在我的观点中,对于 xxx.yy 来说,它是 (5,2) - pnv
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接