【问题标题】:How should I round a float in this case?在这种情况下,我应该如何舍入一个浮点数?
【发布时间】:2012-03-30 13:23:22
【问题描述】:

由于同一个浮点数可以具有多种表示形式,我的代码中存在问题。 例如,这些数字被认为是相同的:

  • 0.0299999400
  • 0.0300000000

我不太在意大精度,我需要计算这些数字的 CRC 并且它们应该是相同的,所以我的方法是使用以下代码:

private static float Rounding(float v, float p)
{
    return Mathf.Round (v * p) / p; 
}

p 是我的精确度。

这似乎运作良好,但在这种情况下,如果我使用 p = 1e7,第一个数字乘法将导致 299999.4 并四舍五入为 299999,变为 0.0299999,而 0.03 将保持为 0.03。那是我的问题。

我做对了吗?也许答案是我不能用这么大的p,但是我不知道浮动是怎么工作的,所以我不知道p的大小到适用于所有情况。

但是,我知道我的浮点值的范围没有浮点范围大(±1.5e−45 到 ±3.4e38)。我的意思是,如果我知道我的浮动范围是 [-100; +100],我可以假设它将有足够的十进制数字 p3。对吗?

还有其他方法吗?

【问题讨论】:

  • 知道范围并不能告诉您精度。单精度浮点的精度约为 7 位小数。
  • @user92546 所以,知道范围不会让我知道小数点后有多少位?
  • 您知道范围远远超过 10^30。这无法告诉您对于大于 10^8 的数字,您无法控制小数点右侧的任何内容。一些双精度格式提供相同的范围,但比单精度格式更高。其他的则以相同的精度提供更大的范围。你不能教 32 位做 256 的工作。

标签: c# floating-point floating-accuracy


【解决方案1】:

您应该将数字转换为decimal,然后将round 转换为所需的精度。 decimals 与它们一样准确,因此您可以例如将它们转换为字符串和哈希,而不会出现任何此类问题。

【讨论】:

  • o.O 小数只使用十进制而不是二进制算术,但它们不是无限准确的。 decimal 也无法准确表示 1/3 之类的东西。
  • @Joey:没错,我的措辞很糟糕;更改为“尽可能准确”。谢谢你的收获。
  • @Jon 谢谢。我不认为你的意思是 return (float) Math.Round(new Decimal(v), digits);,对吧?我没有说重要的事情:除了 CRC,我正在追求确定性模拟,所以我必须接收一个浮点数并返回一个四舍五入的浮点数。我不明白在我有 7 位精度的情况下小数如何使这项工作发挥作用:(
  • @Roberto:返回float 不是我的想法,而是从某个时候开始使用decimal。虽然这听起来像是转换为十进制,但四舍五入然后返回浮点数会导致所有舍入为相同数字的值按位相同的float
【解决方案2】:

我不知道我是否正确,但如果您需要将这两个数字视为相等,您可以使用:

Math.Round(Convert.ToDecimal((float)0.0299999400),2); //result is 0.03
Math.Round(Convert.ToDecimal((float)0.0300000000),2); //result is 0.03

你有它。如果您想将数字四舍五入到 1e7 的精度,那么这两个数字当然会有所不同。

【讨论】:

  • 谢谢。问题在于找到始终有效的精度。
  • @Roberto 我认为您应该更好地解释一下,alwaysworks 对您来说究竟意味着什么?您能否提供更多输入和预期输出的示例?
  • 始终表示范围内的任何浮点数,在我的情况下是 [-100; +100]。有效意味着对于数字的任何浮点表示,在舍入后我将得到按位相同的浮点数。因此,对于我使用的一些 p,我的代码可能会或可能不会工作,我想知道 p 的值可以用来始终工作.
猜你喜欢
  • 2020-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多