sql - 如何在 SQL Server 中获得 float 的精确字符表示?

标签 sql sql-server string floating-point

我们正在对从一个 SQL Server 迁移到另一个 SQL Server 的数据进行一些验证。我们正在验证的一件事是某些数字数据已正确传输。数值数据在新系统中存储为浮点数据类型。

我们知道浮点数据类型存在许多问题,无法保证精确的数字准确性,并且不能对浮点数据使用精确相等比较。我们无法控制数据库模式或数据类型,这些是单独的问题。

在这种特定情况下,我们试图做的是验证某些比率值是否正确传输。具体数据验证规则之一是所有比率都应以小数点右侧不超过 4 位的数字进行传输。

因此,例如,有效比率如下所示:

.7542
1.5423

无效比率为:
.12399794301
12.1209377

我们想要做的是计算小数点右侧的位数,并找出浮点值右侧超过四位数的所有情况。我们一直在使用 SUBSTRING、LEN、STR 和一些其他函数来实现这一点,我相信如果我们将数字字段输入为十进制并将其转换为字符,它会起作用。
但是,我们在尝试将浮点数转换为字符值时发现,SQL Server 似乎总是在两者之间转换为十进制数。例如,当在 SQL Server 企业管理器中查询时,相关字段显示此值:
1.4667

尝试使用 SQL Server 的推荐函数转换为字符串:
LTRIM(RTRIM(STR(field_name, 22, 17)))

返回此值:
1.4666999999999999

我期望的值 如果 SQL Server 直接从 float 转换为 char(然后我们可以从中修剪尾随零):
1.4667000000000000

SQL Server 中是否有任何方法可以直接从浮点数转换为字符,而无需经过中间转换为十进制的过程?我们还尝试了 CAST 和 CONVERT 函数并收到了与 STR 函数相似的结果。

涉及的 SQL Server 版本:SQL Server 2012 SP2

谢谢你。

最佳答案

您的验证规则似乎被误导了。

一个 SQL Server FLOAT , 或 FLOAT(53) , 根据 IEEE 754 标准,内部存储为 64 位浮点数,带有 53 位尾数(“值”)加上一个指数。这 53 个二进制数字对应于大约 15 个十进制数字。

浮点数的精度有限,这并不意味着它们本身“模糊”或不精确,而是并非所有数字都可以精确表示,而必须使用另一个数字来表示。

例如,您的 没有准确的表示。 1.4667 ,而是将其存储为二进制浮点数,(完全)对应于十进制数 1.466699999999999892708046900224871933460235595703125 .正确四舍五入到小数点后 16 位,即 1.4666999999999999 ,这正是你得到的。

由于“SQL Server 中浮点值的精确字符表示”是 1.466699999999999892708046900224871933460235595703125 ,“小数点右边不超过4位”的验证规则显然是有缺陷的,至少如果你把它应用到“精确字符表示”上。

但是,您可以做的是将存储的数字四舍五入到更少的小数位,以便隐藏小数点末尾的小错误。转换为四舍五入到 15 位而不是 16 位的字符表示(还记得开头提到的那些“15 位十进制数字”吗?)会给你 1.466700000000000 ,然后您可以检查前四位后的所有小数是否为零。

关于sql - 如何在 SQL Server 中获得 float 的精确字符表示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37173103/

相关文章:

sql - 德州扑克数据的关系数据库结构

sql-server - 使用 Sql Server Management Studio 2016 导入 bacpac 时出错 - 无法加载文件或程序集 Microsoft.SqlServer.Dac

asp.net - sql server 中 oracle 的 number(2,0) 的替代方案是什么?

c# - 我想在一段时间后拆分一个字符串并将该句子放在一个单独的行上

c# - ComboBox在字符串中搜索,而不仅仅是第一个字母

mysql - 如何使用字符串的前缀(即第一个空格之前的部分)进行分组?

mysql - 指定 WHERE LIKE 子句可以查找

mysql - 更正公式的 SQL 脚本

sql - 无法根据“不在哪里”进行过滤

java - 如何解决 SQLServerException : Invalid object name?