所以我正在做一个小编码的地狱,我遇到了一个问题!现在,这可能是一个重复的问题,但我可以为我的爱找不到任何人有同样的问题,所以这里去;
我试图四舍五入随机生成的双精度,到2个小数点。这在大多数情况下都像预期的那样工作。然而,每隔一段时间,我的代码就会产生多达10+小数的双精度数,这真的很烦人,因为这些值显示在WPF的DataGrid中,DataGrid只是调整大小以适应数字。我用来生成double的代码:
double d = rand.NextDouble() + .5; // I have more of these, differing from + .5 to + 2
然后为了圆它,我用途:
Math.Round(d, 2, MidPointRounding.AwayFromZero);
大多数时候,它的工作原理是简单的,但偶尔,它会产生这样的数字:
0.639999999999999
有谁能解释一下我做错了什么吗?先谢了。
编辑1:所以我没有完全按照我说的去做。如果这与为什么它不会工作有关,我想知道,但我实际上创建我的双打的方式是;
Math.Round(rand.NextDouble() + .5, 2, MidPointRounding.AwayFromZero);
然而,我不明白为什么这会有什么不同,如果一个创建一个双精度型,然后四舍五入,或者如果我只是即时四舍五入一个新创建的双精度型。
编辑2:根据请求,我发布了我的DataGrid代码。XAML和CodeBehind看起来是这样的:XAML:
<DataGrid x:Name="marketDataGrid"
HorizontalAlignment="Left"
Margin="13,225,0,0"
VerticalAlignment="Top"
Height="204" Width="303"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
SelectionMode="Extended"
IsReadOnly="True">
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<EventSetter Event="MouseDoubleClick" Handler="MarketRow_DoubleClick" ></EventSetter>
</Style>
</DataGrid.Resources>
双击事件背后的代码:
private void MarketRow_DoubleClick(object sender, RoutedEventArgs e)
{
DataGridRow row = sender as DataGridRow;
Company c = (Company)marketDataGrid.SelectedItem;
BuyWindow bw = new BuyWindow(c, pc, this);
bw.Show();
}
我添加对象列表的代码
marketDataGrid.ItemsSource = cc.GetCList();
marketDataGrid.Items.Refresh();
请让我知道如果你需要更多。如果你想看的话我可以把整个项目上传到别的地方。这样做我可能会有点尴尬,因为我的代码并不是从头到尾都很漂亮。
可能是我打错了...但我不这么认为。我已经仔细研究过解决方案了。
1条答案
按热度按时间ncecgwcz1#
根据
double
的本质,在101个数学值0.50, 0.51, 0.52, ..., 1.48, 1.49, 1.50
中,只有5(即0.50
和0.75
和1.00
和1.25
和1.50
)可以精确表示。所有其他的(0.51
和0.52
等)将有一个内部表示,不同于数学上精确的两位小数值。(You可以使用
int
(从50
到150
)或decimal
(从0.50m
到1.50m
)来避免这种情况。出于这个原因,这一切都归结为如何将内部
double
表示格式化为可显示的数字和分隔符字符串。您说您使用WPF,但没有提供有关网格中使用的格式的更多信息。我不确定WPF是否使用
double.ToString
或其他机制。在提出这个问题的时候,.NET(当时称为.NET Core)和.NET Framework都使用了不符合IEEE标准的
double.ToString
实现。在这种非标准的实现中,使用格式字符串"G17"
在某些情况下可能会显示部分表示不准确。例如,(0.51).ToString("G17")
给出了字符串"0.51000000000000001"
(十进制分隔符.
依赖于当前的CultureInfo
)。然而,像(0.62).ToString("G17")
这样的东西只给出了"0.62"
,因为在这种情况下,17位有效数字不足以揭示差异。从2019年(.NET Core 3.0)开始,.NET中的格式与.NET Framework中的格式之间存在显着差异。前者现在使用更兼容的算法,而后者仍然使用旧的非标准实现。
在2019年之后的.NET中,您可以要求比17更多的数字。例如,
(0.51).ToString("G40")
现在给出"0.5100000000000000088817841970012523233891"
,(0.62).ToString("G40")
给出"0.6199999999999999955591079014993738383055"
。你可以在这里阅读更多关于这些突破性变化的信息。有一个链接到坦纳古丁的博客文章Floating-Point Parsing and Formatting improvements in .NET Core 3.0。正如我所说的,我不确定WPF在2016年(2019年之前)是否使用了.NET的非标准格式逻辑,或者有自己的格式逻辑。也许它有自己的。这将需要一个WPFMaven(不是我),可能还有一些关于你的设置的额外信息,来回答。