Firebird 是否支持 Infinity 作为 FLOAT 值?

Does Firebird support Infinity as FLOAT value?

Firebird 支持特殊浮点值 Infinity-Infinity 作为 DOUBLE PRECISION 值:

select log(1, 1), log(1, 0.5), log(1, 1.5) from RDB$DATABASE

这会产生

|LOG|LOG      |LOG      |
|---|---------|---------|
|NaN|-Infinity|+Infinity|

The trick using LOG() with base 1 is documented here。虽然 NaN 也作为 FLOAT 值存在:

select cast(log(1, 1) as float) from RDB$DATABASE

无穷大不能转换为 FLOAT:

select cast(log(1, 1.5) as float) from RDB$DATABASE

我得到:

SQL Error [335544916] [22003]: arithmetic exception, numeric overflow, or string truncation; numeric value is out of range [SQLState:22003, ISC error code:335544916]

在 Firebird 中是否有任何记录或未记录的方法来获取 FLOAT 类型的无穷大?

答案很复杂。尽管 Firebird 的浮点类型在某些情况下可以 hold/store NaN 和 Infinity,但它不支持 Infinity 转换为 FLOAT (因此,赋值转换也不支持),因为转换为 float 执行范围检查,-Infinity 和 +Infinity 超出范围。

我不确定这是不是故意的,但可能给出了标准中如何指定 CAST(尽管 NaN 的行为是有问题的)。事实上,我什至不确定对 NaN 和 Infinity 的支持是有意的行为,还是支持 NaN 和 Infinity 的底层实现的副作用。

例如可以存储无穷大:

public static void main(String[] args) throws SQLException {
    try (var connection = DefaultDb.createDefaultConnection();
         var pstmt = connection.prepareStatement("insert into withfloat(floatval) values (?)")) {
        pstmt.setFloat(1, Float.POSITIVE_INFINITY);
        pstmt.execute();
    }
}

然而,据我所知,没有办法在 DSQL 本身中产生这些值。

我建议将此报告为 http://tracker.firebirdsql.org/browse/CORE 上的错误,但我不确定该错误是完全可以生成和存储 NaN/Infinity,还是CAST。而且我担心修复其中任何一个也是有问题的:不允许是向后不兼容的,而允许 CAST 会违反标准。

郑重声明,SQL 标准并未针对浮点类型指定任何有关 NaN 和 Infinity 的内容,但该规范的其余部分明确指出不应支持 NaN 和 Infinity。例如,对于 LOG,它指定:

  1. If <general logarithm function> is specified, then let VB be the value of the <general logarithm base> and let VA be the value of the <general logarithm argument>.
    Case:
    a) If at least one of VA and VB is the null value, then the result is the null value.
    b) If VA is negative or 0 (zero), then an exception condition is raised: data exception — numeric value out of range.
    c) If VB is negative, 0 (zero), or 1 (one), then an exception condition is raised: data exception — numeric value out of range._ d) Otherwise, the result is the logarithm with base VB of VA.

换句话说,LOG(1, _) 应该引发 数据异常——数值超出范围,而不是产生 NaN 或 +/-Infinity。