我的数据库有一个表,该表的列包含双精度值数组。该表如下所示:
| id | set_name | data |
--------------------------
| 1 | data_1 | {1...} |
我写了一个存储的函数,它以称为set_name
的复合类型返回data
和data_obj
,它只包含两个属性,set_name
为TEXT
,data
为DOUBLE PRECISION[]
。
data
数组中的大多数值都包含几个小数位,例如32.433787。我正在尝试使用Npgsql将数据提取到C#中,这很好用,除了在1,000个值的数组中有一个值之外,该值从Postgres数据库到C#是不同的。
在这种情况下,我正在使用Npgsql向该表添加一行,其中该数组包含一个值为32.433787的元素。使用pgAdmin,我可以看到32.433787确实是存储的值,或者至少是显示的值。当我使用INpgsqlNameTranslator
将这些数据提取到我的C#代码中时,此点的结果值为32.433787000005。
这是我的C#代码的相关代码段:
public class DataObj : INpgsqlNameTranslator
{
public string SetName {get; set;}
public double[] Data {get; set;}
public string TranslateMemberName(string clrName)
{
if (clrName == "Data") return "data";
else if (clrName == "SetName") return "set_name";
else throw new ArgumentException();
}
public string TranslateTypeName(string clrName) { return "data_obj"; }
}
我的想法是从Postgres DOUBLE PRECISION
到.NET double
的转换是引入了额外的小数位。我曾尝试在Postgres中切换到NUMERIC
,但遇到了同样的问题。如何补救?
浮点数以二进制形式存储,因此当它们转换为小数时总是存在一些不精确性。超出一定精度后,数字将变得“不重要”,即它们是噪音。
通常,PostgreSQL会禁止显示这些无关紧要的数字,但我想.Net不会。如果将参数extra_float_digits
设置为3,您也可以在PostgreSQL中看到这些数字。
因此无需担心;这是double precision
所期望的。如果需要精确数字,请使用numeric
。