wpf Math.Round(double d,2,MidPointRounding.AwayFromZero)产生许多小数

k4aesqcs  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(96)

所以我正在做一个小编码的地狱,我遇到了一个问题!现在,这可能是一个重复的问题,但我可以为我的爱找不到任何人有同样的问题,所以这里去;
我试图四舍五入随机生成的双精度,到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();

请让我知道如果你需要更多。如果你想看的话我可以把整个项目上传到别的地方。这样做我可能会有点尴尬,因为我的代码并不是从头到尾都很漂亮。
可能是我打错了...但我不这么认为。我已经仔细研究过解决方案了。

ncecgwcz

ncecgwcz1#

根据double的本质,在101个数学值0.50, 0.51, 0.52, ..., 1.48, 1.49, 1.50中,只有5(即0.500.751.001.251.50)可以精确表示。所有其他的(0.510.52等)将有一个内部表示,不同于数学上精确的两位小数值。
(You可以使用int(从50150)或decimal(从0.50m1.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(不是我),可能还有一些关于你的设置的额外信息,来回答。

相关问题