SQLite 浮点问题
SQLite floating point issue
这个查询 returns 1.7763568394002505e-15 当它应该 return 0.00:
SELECT st.id
, Sum(
CASE sa.Type
WHEN 4 THEN sa.quantity * (st.price - st.commission)
WHEN 5 THEN -sa.quantity * (st.price - st.commission)
ELSE 0.0 END
) Sales
FROM sales sa
JOIN stock st
ON sa.stockid = st.id
WHERE st.id = 1
GROUP BY st.id
http://sqlfiddle.com/#!5/cccd8/3
这看起来像是典型的浮点计算问题,但我该如何解决?
我已尝试将各个列转换为 REAL,但没有任何区别。
您可以使用此查询模拟结果:
SELECT 26.3 - 10.52 - 15.78 AS Result
SQLite 的 REAL 不适合货币。 SQlite 不支持 SQL 小数或 SQL 数字数据类型,因此最好的选择是使用整数,并将值存储为分。
CREATE TABLE stock (
id INTEGER,
-- Store price and commission as integers, implying that price is in cents,
-- (.20 is stored as 320) and commission is a two-digit percentage (0.57%
-- is stored as 57). This is how scaled integers work in general.
price integer,
commission integer,
PRIMARY KEY(id)
);
CREATE TABLE sales (
id INTEGER,
stockid INTEGER,
type INTEGER,
quantity INTEGER,
PRIMARY KEY(id)
);
insert into stock values (1, 320, 57);
insert into sales values (1, 1, 4, 10);
insert into sales values (2, 1, 5, 4);
insert into sales values (3, 1, 5, 6);
这个查询,来自你的 SQLfiddle,正确 returns 0。
SELECT st.id
, Sum(
CASE sa.Type
WHEN 4 THEN sa.Quantity * (st.price - st.commission)
WHEN 5 THEN -sa.Quantity * (st.price - st.commission)
ELSE 0.0 END
) Sales
FROM sales sa
JOIN stock st
ON sa.stockid = st.id
WHERE st.id = 1
GROUP BY st.id;
id Sales
---------- ----------
1 0
转换为更合适的数据类型(不是 为 REAL)将隐藏 一些问题——甚至可能是大多数问题,甚至是所有问题他们在一个特定的应用程序。但是转换不会解决它们,因为存储的值可能与您真正想要的值不同。
Mike Sherrill 是正确的,您可能应该使用整数。但是为了快速修复,您可以将 Sum
调用包装在 Round(__,2)
中以四舍五入到最接近的美分。
这个查询 returns 1.7763568394002505e-15 当它应该 return 0.00:
SELECT st.id
, Sum(
CASE sa.Type
WHEN 4 THEN sa.quantity * (st.price - st.commission)
WHEN 5 THEN -sa.quantity * (st.price - st.commission)
ELSE 0.0 END
) Sales
FROM sales sa
JOIN stock st
ON sa.stockid = st.id
WHERE st.id = 1
GROUP BY st.id
http://sqlfiddle.com/#!5/cccd8/3
这看起来像是典型的浮点计算问题,但我该如何解决? 我已尝试将各个列转换为 REAL,但没有任何区别。
您可以使用此查询模拟结果:
SELECT 26.3 - 10.52 - 15.78 AS Result
SQLite 的 REAL 不适合货币。 SQlite 不支持 SQL 小数或 SQL 数字数据类型,因此最好的选择是使用整数,并将值存储为分。
CREATE TABLE stock (
id INTEGER,
-- Store price and commission as integers, implying that price is in cents,
-- (.20 is stored as 320) and commission is a two-digit percentage (0.57%
-- is stored as 57). This is how scaled integers work in general.
price integer,
commission integer,
PRIMARY KEY(id)
);
CREATE TABLE sales (
id INTEGER,
stockid INTEGER,
type INTEGER,
quantity INTEGER,
PRIMARY KEY(id)
);
insert into stock values (1, 320, 57);
insert into sales values (1, 1, 4, 10);
insert into sales values (2, 1, 5, 4);
insert into sales values (3, 1, 5, 6);
这个查询,来自你的 SQLfiddle,正确 returns 0。
SELECT st.id
, Sum(
CASE sa.Type
WHEN 4 THEN sa.Quantity * (st.price - st.commission)
WHEN 5 THEN -sa.Quantity * (st.price - st.commission)
ELSE 0.0 END
) Sales
FROM sales sa
JOIN stock st
ON sa.stockid = st.id
WHERE st.id = 1
GROUP BY st.id;
id Sales ---------- ---------- 1 0
转换为更合适的数据类型(不是 为 REAL)将隐藏 一些问题——甚至可能是大多数问题,甚至是所有问题他们在一个特定的应用程序。但是转换不会解决它们,因为存储的值可能与您真正想要的值不同。
Mike Sherrill 是正确的,您可能应该使用整数。但是为了快速修复,您可以将 Sum
调用包装在 Round(__,2)
中以四舍五入到最接近的美分。