【问题标题】:POWER does not reverse LOG and vice versaPOWER 不反转 LOG,反之亦然
【发布时间】:2019-01-03 19:25:23
【问题描述】:

我对 POWER/LOG 的问题是,虽然它们似乎适应了您发送的数据类型(输出变量类型与第一个变量的类型匹配),但精度似乎停止接近浮点数的限制,导致输出不正确。 示例:

DECLARE @ten numeric(18,4) = 10
declare @num numeric(18,4) = 234567890
SELECT power(@ten,log(@num,@ten))

输出 = 234567890.0000 哪个是正确的

但是,如果我们提高精度,如下:

DECLARE @ten numeric(18,6) = 10
declare @num numeric(18,6) = 234567890
SELECT power(@ten,log(@num,@ten))

输出 = 234567889.999999 这是不正确的,但四舍五入可以解决它(?)

最后,如果将精度更改为 Numeric(18,9) 之类的值,问题会变得更糟:

DECLARE @ten numeric(18,9) = 10
declare @num numeric(18,9) = 234567890
SELECT power(@ten,log(@num,@ten))

输出 = 234567889.999999310 这是不正确的,四舍五入也无法解决。

我假设问题是虽然 POWER 和 Log 函数可以接受非常精确的数据类型,但它们的工作变量必须是浮点类型?有没有人有这方面的经验,或者有解决它的经验?

【问题讨论】:

  • 您是否有数据表明 a) 在这些范围内是精确的并且 b) 差异在哪里很重要?如果是这样,那么您属于一个非常罕见的群体,并且使用通用构造似乎与您想要的相反。
  • 我实际上存储了不同精度的日志,我需要将日志反转为某个固定精度,这样才能得到准确的答案。在上面的示例中(使用 234567890 的奇异数据集),似乎允许的最大精度为 4。如果我想要更多,就不可能找回原来的价值。
  • 您应该更仔细地考虑您的输入数据并适当地限制您的输出。即使在此对数/电源工作之前,您的测量精度也不可能达到 9 位数。
  • LOG 可以很容易地用简单的整数参数表示,这些参数在十进制类型中具有重复的十进制表示。如果不(我相信)切换到使用代数/符号逻辑来表示中间状态的系统,您将无法执行日志/电源往返。你肯定不能使用固定空间类型来做到这一点。
  • 以精度为例。如果您正在测量长度,您是否真的声称您可以在高达 1000 公里的范围内以 毫米 精度测量距离?因为这就是您声称的 9 位精度,更不用说 18 位了。

标签: sql sql-server math-functions


【解决方案1】:

我认为问题在于LOG 的返回类型是FLOAT,而不是您传入的数据类型。FLOAT用于浮点数值数据的近似数字数据类型。浮点数据是近似的;因此,并非数据类型范围内的所有值都可以准确表示

另一方面,POWER 接受一个 float 类型或可以隐式转换为 float 的类型的表达式。 作为输入,并返回 依赖的类型 em> 在浮点表达式的输入类型上。意思是,对于DECIMAL的输入,它将返回DECIMAL

因此,在您的情况下,LOG 返回一个 FLOAT,该 POWER 返回一个 FLOAT,正如所引用的那样,它并不精确。

【讨论】:

  • 谢谢,我以为我已经检查过 LOG 的输出是否像 POWER 一样适应,但显然不是。我猜没有一种简单的方法可以获取具有更精确数据类型的日志函数?
  • Newp,正如 Damien 和 Gordon 指出的那样,SQL Server 很难确定要做什么......不同的用户会希望它以不同的方式处理(舍入、截断、你有什么)跨度>
【解决方案2】:

可以通过两种不同的方式处理非整数:使用定点算术或浮点算术。这两种方法都会引入错误。

log() 函数被记录为接受 float 作为参数并返回 floatpower() 的行为有点不同。第一个参数被转换为float,但它也决定了返回类型。这就是为什么返回类型的规模是由@ten的规模驱动的。

所有发生的事情是您看到的值完全相同,但比例不同。这个数字略有偏差并不奇怪——舍入问题是计算机上非整数运算的一个已知问题。

一点也不意外。 234567889.9999993145465850830 是正在生成的值。它是 SQL Server 能够得出的最接近实际答案的结果——并且足够接近大多数工作。

【讨论】:

  • 是的,我想我只是想知道是否有人找到了更精确的 POWER/LOG 的解决方案(尽管在你回答之后,看来我只需要更精确的 LOG 函数)。谢谢。
  • @KeithZink 你可能需要一个 CLR。 F.e.就像this old SO post中的赏金答案一样。
  • 非常感谢,我以为我搜索过类似的东西,我想我的下一个问题应该是如何有效地搜索。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 2011-10-08
  • 2020-10-24
  • 2013-03-15
  • 2014-01-23
  • 2019-09-19
相关资源
最近更新 更多