Don*_*ott 4 c# floating-point double
我有一个需要转换为当前表单的数据库表.这个表有三列Double类型(Pervasive.SQL如果有人关心的话).
我的问题是这个表已经存在了很长时间,并且代码可以追溯到15年或更长时间.
从历史上看,我们一直使用Double.MinValue(或当时的任何语言)来表示"blank"用户提供的值.换句话说,缺少一个值实际上存储为一个我们以后可以识别的值并且智能地作出反应.
所以,今天我的问题是我需要遍历这些记录并将它们插入到新创建的表中(这是我所说的"转换").但是,我没有在转换的表中看到一致的值.以下是我肯定知道的:
2.2250738585072014E-308
3.99285938963E-313
3.99099435427E-313
1.1125369292536007E-308
-5.389000690742776E279
2.104687961E-314
Run Code Online (Sandbox Code Playgroud)
现在,我认识到还有其他方法Double.MinValue可能存在或者至少可以代表.做了一些谷歌搜索,我发现第一个是另一种表示Double.MinValue(实际上DBL_MIN在这里引用:http://msdn.microsoft.com/en-us/library/6bs3y5ya (v = vs.100 ) .aspx).
我不想太啰嗦,所以如果这些信息不足以帮助我,我会征求问题.可以这么说,我需要一种可靠的方法来发现所有以前的"最小值"值,并用C#Double.MinValue常量替换它们,因为我正在循环这些数据行.
如果它被证明是dataRow["Value"] < someConstant,那就这样吧.但我会让数学理论家用这个决心帮助我.
谢谢你的时间.
编辑:
这是我在找到它们时对这些值所做的事情.它是汇总要写入数据库的值的泛型方法的一部分:
else if (c.DataType == typeof(System.Double))
{
if (inRow[c] == DBNull.Value)
retString += @"NULL";
else
{
Double d;
if (Double.TryParse(inRow[c].ToString(), out d))
retString += d.ToStringFull();
}
}
Run Code Online (Sandbox Code Playgroud)
到现在为止,它只是接受了它们.这是不好的,因为当找到他们,他们看起来像可接受的数据,而不是像Double.MinValue.因此,不被视为空白.但那就是它们.
这完全是疯狂的.让我们详细看一下这些数字.这些都是微小的数字,只是勉强大于零:
2.2250738585072014E-308
Run Code Online (Sandbox Code Playgroud)
这是1/2 1022 - 这是正常的双倍.这是你集合中两个"特殊"数字之一; 它是大于零的最小正常双精度.你名单上剩下的小双打是低于正常的双打.
1.1125369292536007E-308
Run Code Online (Sandbox Code Playgroud)
这是1/2 1023 - 它是一个低于正常的双倍.这也是一个特殊的数字; 它是大于零的最小正常双倍的一半.(我原来说这是最大的次正常双倍但当然不是真的;请参阅评论.)
3.99285938963E-313
Run Code Online (Sandbox Code Playgroud)
这不是什么特别的事.它是一个次正规的双倍,等于分子为154145的分数,分母是2的相当大的幂.
3.99099435427E-313
Run Code Online (Sandbox Code Playgroud)
这也不是什么特别的事.这次分子是154073.
2.104687961E-314
Run Code Online (Sandbox Code Playgroud)
这也不是什么特别的事.分子是2129967929,分母是两个更大的幂.
到目前为止,所有数字都非常接近零和正数.这个数字远非零和负数,因此突出:
-5.389000690742776E279
Run Code Online (Sandbox Code Playgroud)
但同样没有什么特别的; 它甚至没有接近绝对值最大的负双峰,大约是-1.79E308,大约十亿倍.
这是一个完整的混乱.
我的建议是立即停止这种疯狂.它使绝对没有任何意义,以使用值是令人难以置信的接近零代表"空白"的价值观; 非常接近零的值应舍入为零,不作为空白处理!
Double已经有"空白"值的代表,即Double.NaN - Not A Number ; 当域已包含特定的"无效"值时,使用有效值表示无效值是很奇怪的.(请记住,实际上存在大量不同的NaN位模式;使用IsNaN来确定双精度是否为NaN.)
所以我的建议是:
单独检查数据库中每个正常或非常小的正常双精度数.其中一些可能应该为零,并且由于舍入误差而最终变为微小值.用零替换它们.那些应该是空白的,用数据库null替换(最佳实践)或双NaN(可接受,但不如数据库null.)
编写一个程序来查找数据库中绝对值不可能很大的每个数字,并用数据库null或double NaN替换它.
更新所有客户端,以便他们了解您用于表示空值的约定.