首页 > 解决方案 > Firebird 是否支持 Infinity 作为 FLOAT 值?

问题描述

Firebird 支持特殊的浮点值Infinity-InfinityasDOUBLE PRECISION值:

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

这产生

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

此处记录了使用LOG()with base的技巧1。WhileNaN也作为FLOAT值存在:

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

无穷大不能转换为FLOAT

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

我越来越:

SQL 错误 [335544916] [22003]:算术异常、数值溢出或字符串截断;数值超出范围 [SQLState:22003,ISC 错误代码:335544916]

是否有任何记录或未记录的方法可以FLOAT在 Firebird 中获得无限类型?

标签: sqlfloating-pointfirebird

解决方案


答案是,很复杂。尽管 Firebird 的浮点类型在某些情况下可以保存/存储 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. 如果指定了<general logarithm function>,则令VB 为<general logarithm base> 的值,令VA 为<general logarithm argument> 的值。
    案例:
    a) 如果 VA 和 VB 至少有一个是空值,那么结果是空值。
    b) 如果 VA 为负数或 0(零),则引发异常条件:数据异常 — 数值超出范围
    c) 如果 VB 为负数、0(零)或 1(一),则引发异常情况:数据异常 — 数值超出范围。_ d) 否则,结果为 VA 以 VB 为底的对数。

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


推荐阅读