Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用CS驱动程序在Mongodb中进行浮点不精确舍入_Mongodb_Mongodb .net Driver - Fatal编程技术网

使用CS驱动程序在Mongodb中进行浮点不精确舍入

使用CS驱动程序在Mongodb中进行浮点不精确舍入,mongodb,mongodb-.net-driver,Mongodb,Mongodb .net Driver,当我使用csharp驱动程序将浮点数保存到MongoDB中时,它并没有准确保存。如果我的号码是1504.57,我希望数据库会有相同的号码,但由于某种原因,它会变成1504.56994628906(在MongoDB中使用双输入)。发生什么事?如何准确地保存数据 “我的对象”将所有字段保留为对象类型,并根据类型动态强制转换它们,例如: this.Values[i] = float.Parse(this.Values[i].ToString()); 也许这就是这种奇怪行为的原因?但在铸造了这个之后

当我使用csharp驱动程序将浮点数保存到MongoDB中时,它并没有准确保存。如果我的号码是1504.57,我希望数据库会有相同的号码,但由于某种原因,它会变成1504.56994628906(在MongoDB中使用双输入)。发生什么事?如何准确地保存数据

“我的对象”将所有字段保留为对象类型,并根据类型动态强制转换它们,例如:

 this.Values[i] = float.Parse(this.Values[i].ToString());
也许这就是这种奇怪行为的原因?但在铸造了这个之后,.Values[i]是相当准确的,它只在数据库中被破坏了。 谢谢

更新。 压缩数据的类: 公共类TransferredData { [b单一元素(“_id”)] [脚本忽略] 公共对象Id{get;set;}

    public class Data
    {
        public List<Object> Values { get; set; }
        public DateTypes DataType { get; set; }
        public void CastToType()
        {
            for (int i = 0; i < this.Values.Count; i++ )
            {
                if (this.DataType == DateTypes.Date)
                {
                    DateTime dt = DateTime.Parse(this.Values[i].ToString());
                    this.Values[i] = dt.ToUniversalTime().Date;
                }
                else if (this.DataType == DateTypes.Other)
                {
                    this.Values[i] = this.Values[i].ToString();
                }
                else if (this.DataType == DateTypes.Reading)
                {
                    this.Values[i] = float.Parse(this.Values[i].ToString());
                }
            }
        }
    }
公共类数据
{
公共列表值{get;set;}
公共日期类型数据类型{get;set;}
public void CastToType()
{
对于(int i=0;i
}

我使用对象类型,因为我不知道它可能是哪种实际类型。所以,在执行upsert之前,我用数据填充这个类,然后调用Cast方法

Then I save it into db:
data = new TransferredData();
...
data.Values[1] = "1504.57"; // Because the input is always string
data.CastToType(); // Here data.Values[1] = 1504.57 - cool
TransferredDataCollection.Save<TransferredData>(data, SafeMode.True);
然后我将其保存到数据库中:
数据=新的TransferredData();
...
数据.值[1]=“1504.57”;//因为输入总是字符串
data.CastToType();//此处data.Values[1]=1504.57-冷
TransferredDataCollection.Save(数据,SafeMode.True);

在这一刻之后,查看数据库。。。它是1504.56994628906

我想这与1504.57表示为双精度浮点有关


可能有两种选择,一种是舍入多余的数字,另一种是如果数字是货币,则存储美分而不是美元。

IEEE 754浮点格式无法准确表示每个数字。因此,您的问题无法避免,并按预期工作

如果您需要输入=输出的绝对保证,而无法保证使用的浮点格式能够准确表示输入,则不应使用浮点格式


大多数人在试图将货币价值储存在浮动货币中时都会遇到这些问题,这被普遍认为是一个极其糟糕的想法。如果您需要存储货币值,请将其另存为整数值,通常为美分。

我将附和上面的所有评论,即浮点数在从十进制转换为二进制以及从十进制转换回二进制时通常会出现有趣的舍入错误

在您的特定情况下,舍入错误是由C语言本身引入的,而不是由C驱动程序引入的。MongoDB本身不支持单精度浮点数,因此在发送到数据库之前,C#驱动程序会将C#float值转换为双倍。正是在这种转换过程中,才会出现舍入误差

下面是一小段C#代码,演示了将浮点转换为双精度浮点如何引入舍入错误:

var f = (float)1504.57;
var d = (double)f;

Console.WriteLine(f);
Console.WriteLine(d);

正如其他人所建议的,如果必须具有100%的精度,则应使用除float或double之外的其他数据类型。

能否提供再现问题的代码?我相信这与float本身的二进制表示有关,一个很好的方法是*10或将其存储为字符串或双助手(如果您的驱动程序有一个)虽然有关浮点不准确的帖子是正确的,但我认为您在代码中使用的是
float
而不是
double
,这可能会使情况变得更糟。试着把你的代码改成双倍。@JohnnyHK,我也试过这个了。即使在调试过程中代码中出现了两倍,它仍然是1504.57,但一旦将其放入数据库,它就变得不准确了。