1

在 C# 中,如何在没有舍入的情况下修复小数类型的点后位数。

例如:十进制坐标 = 47.483749999999816;(地理坐标的一部分)

我只需要在点后保留 6 位数:47.483749

4

3 回答 3

6

你可能会使用

decimal truncated = Math.Truncate(coords * 1000000m) / 1000000m;

或许

decimal truncated = Math.Truncate(coords / 0.000001m) * 0.000001m;

在这两个中,我开始更喜欢后者。该数字0.000001m在内部表示为尾数1和 scale 6,因此除以它实际上只是将小数点移动了六位。

最后乘以的方法0.000001m往往会给出小数点后正好六位数的结果,即使必要时尾随零也是如此。例如coords = 1.23m会导致truncated1.230000m

如评论中所述,上述技术都会导致OverflowExceptionifcoords太大(超过 百万分之一decimal.MaxValue)。

为了完整起见,这里有几个其他的解决方案:

decimal truncated = coords - coords % 0.000001m;

这似乎工作正常。虽然尾随零的数量并不总是正确的,但我相信它会给出相同的结果。运算符==(或decimal.Equals)。

最后,您可以使用:

decimal truncated = Math.Round(coords - 0.0000005m, 6, MidpointRounding.AwayFromZero);

但这仅适用于非负数coords

如果您真正需要的是格式化string,请调用ToString重载 on truncated。但请注意,正如我所指出的,尾随零。如果你使用.ToString("F6"),应该总是有六位小数。

当然,您也可以使用字符串操作进行截断。它会是这样的:

string coordsString = coords.ToString(CultureInfo.InvariantCulture);
int idxOfPoint = coordsString.IndexOf(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator);
if (idxOfPoint != -1 && coordsString.Length > 6 + 1 + idxOfPoint)
    coordsString = coordsString.Remove(6 + 1 + idxOfPoint);

// coordsString is now truncated correctly.
// If you need a decimal, use decimal.Parse(coordsString)
于 2013-02-26T07:34:24.507 回答
0

非常棘手,不建议,但我真的不知道你在寻找什么解决方案(因为你正在避免rounding):

double k = 47.483749999999816;
k = double.Parse(Regex.Replace(k.ToString(), @"(\d+\.\d{6})(.\d+)", x => x.Groups[1].Value));
Console.WriteLine(k);

打印

47.483749
于 2013-02-26T07:36:08.400 回答
0

您可以使用

   decimal.Round( 47.483749999999816, 6)
于 2013-02-26T07:39:51.390 回答