我们正在对从一个 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/