如何从 SQLite 数据库中 select 浮点无限文字?

How do I select floating-point infinity literals from a SQLite database?

我有一个名为table的SQLite数据库,名为measurements,其中包含一些通过功率计测量的实验数据。它们作为数据类型 REAL 存储在名为 power_dbm 的字段中。在某些测量中,读数可能会超出刻度,仪表会因超量程或欠量程而无法获得读数,因此使用值 +Inf-Inf 来表示这些值。

比如这里是部分数据

sqlite> SELECT power_dbm, typeof(power_dbm) from measurements;
-10.312|real
-9.908|real
-11.344|real
-Inf|real

如你所见,有一个负无穷大的浮点数。不幸的是,我不知道从数据库中 select 这些值的正确语法。我试过了:

sqlite> SELECT freq_hz, power_dbm from measurements WHERE power_dbm=-Inf;
Error: no such column: Inf

sqlite> SELECT freq_hz, power_dbm from measurements WHERE power_dbm='-Inf'
(nothing returned)

sqlite> SELECT freq_hz, power_dbm from measurements WHERE power_dbm='-infinity';
(nothing returned)

sqlite> SELECT freq_hz, power_dbm from measurements WHERE power_dbm=-1/0;
(nothing returned)

sqlite> SELECT freq_hz, power_dbm from measurements WHERE power_dbm is -1/0;
(incorrect results returned, power_dbm is null instead of negative infinity)

在 SQL/SQLite 中指定正无穷大或负无穷大的字面值的正确语法是什么?对相关文档的任何其他参考也将不胜感激。

解决方案 1:使用 impossibly-huge floating-point 文字

我发现写一个 impossibly-huge floating-point 文字如 9e999 是构造 +Inf/-Inf.

的一种方法
sqlite> SELECT 9e999;
Inf

sqlite> SELECT -9e999;
-Inf

sqlite> SELECT freq_hz, power_dbm, typeof(power_dbm) FROM measurements
   ...> WHERE power_dbm=-9e999;
370000000|-Inf|real
440000000|-Inf|real
510000000|-Inf|real
580000000|-Inf|real

解决方案 2:将 ieee754() 与硬编码 exponent/significand 一起用于 Infinity

您可以通过函数 ieee754() 从 IEEE 754 表示中的指数和尾数手动构造 +Inf-Inf。这是我在找到 9e999 技巧之前使用的原始解决方案...

sqlite> SELECT ieee754(4503599627370496, 972);
Inf

sqlite> SELECT ieee754(-4503599627370496, 972);
-Inf

sqlite> SELECT freq_hz, power_dbm, typeof(power_dbm) FROM measurements
   ...> WHERE power_dbm=ieee754(-4503599627370496, 972);
370000000|-Inf|real
440000000|-Inf|real
510000000|-Inf|real
580000000|-Inf|real

ieee754()和其他相关函数的详细用法在Floating Point Numbers中有记载。

解决方案 3:使用参数化 SQL 查询

使用 ieee754(-4503599627370496, 972) 感觉比像 9e999 这样的随机值更严格,但是 9e999 足以让您在控制台中手动输入命令,而您想要的只是快速查看数据,因此正确性不是真正的问题。

在实际程序中,人们会使用参数化 SQL 查询而不是处理字符串,只需传递本机 Infinity 常量(例如 Python 的 math.inf) 用你的编程语言就足够了。

$ python3
Python 3.9.9 (main, Nov 19 2021, 00:00:00) 
[GCC 10.3.1 20210422 (Red Hat 10.3.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> import sqlite3
>>> DB_FILE = "./data.db"
>>> con = sqlite3.connect(DB_FILE)
>>> cur = con.cursor()
>>> cur.execute(
...     "SELECT power_dbm from measurements "
...     "WHERE power_dbm=?", (-math.inf,)).fetchall()
[(-inf,), (-inf,), (-inf,), (-inf,)]

选角适合我:

SELECT power_dbm from measurements WHERE CAST(power_dbm AS CHARACTER) ='Inf';