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
,它指定:
- 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。
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
,它指定:
- 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。