【问题标题】:Should I use Decimal type as keys in a Dictionary?我应该使用小数类型作为字典中的键吗?
【发布时间】:2013-01-19 13:19:29
【问题描述】:

我即将创建一个字典,其中每个值都有一个数字键,通过实验计算获得。

我知道double 和任何其他浮点类型都不太适合用作键,因为很难比较两个浮点数的唯一性或相等性。

有谁知道Decimal 在这方面是否是一个好的候选人?另一种方法是将双精度转换为具有给定精度的字符串,但这在我看来是一种不优雅的解决方法。

【问题讨论】:

  • 为什么要使用十进制数作为字典中的键?它可以帮助我们为您提供最佳解决方案。
  • 我的仪器返回一个输入角度列表中每个项目的列表。因此,域自然映射将是一个字典,其中每个键都是一个实数(在数学意义上)。这个数字将用于计算,但大约六位数的精度就可以了(仪器的精度要低得多)。
  • 好的,但为什么要字典?字典的值是什么?
  • 这些值是照片中已投影水平条纹图案的像素位置列表,每个条纹与水平面有一个角度。
  • @CédricBignon 但老实说,我认为角度不是真正的输入,而是“条纹”或“边缘”对象的属性。也许我会重新制定我的实现,但“作为字典键的数值”问题仍然有效且相关:)

标签: c# .net dictionary key decimal


【解决方案1】:

我知道这是一个老问题,但我相信我的回答可以帮助别人。

我真的需要浮动键。

当然,我遇到了精度问题,我的字典比它需要的大得多(我希望它例如 1.00.999998 被视为相同)。使用固定数量的十进制数字不是一个很好的解决方案(例如,按照 OP 的建议将其转换为字符串),因为它使用绝对误差进行比较,而相对误差更为普遍。

我最终写了以下方法:

float Quantize(float x)
{
    const float relMaxQuantError = 0.001f;

    float ret = Mathf.Log10(Mathf.Abs(x));
    float quantum = Mathf.Log10(1+relMaxQuantError); 
    ret = Mathf.Floor(ret/quantum) * quantum;
    ret = Mathf.Sign(x) * (Mathf.Pow(10, ret));

    return ret;
}

在将浮点数存储到字典之前,我使用此方法量化浮点数。 const 可以控制最大允许的相对误差(目前为 0.1 %)。

PS:Mathf 是 Unity 的类。它可以很容易地调整为使用标准的Math

【讨论】:

    【解决方案2】:

    如果您使用decimaldouble 因为int 不够大,请考虑改用long

    另外,我认为比较 decimals 或 doubles 应该没问题,只要没有小数/小数部分,并且只包含整数(-1,0,1,2,3 等)

    (虽然我不建议在比较重要的地方使用decimal/double,以避免将来出现任何意外错误)

    如果您只处理 6 位精度,则转换为 int 应该没问题。

    【讨论】:

      【解决方案3】:

      使用floatdecimal 作为字典中的键没有太大区别。两者都用指数表示数字 - 所以两者都遭受相同的比较问题,只是规模不同。

      如果您需要按位相等,对于 Dictionary 都可以,如果您需要“大约相同的值”的键,则需要将其设为自定义键,该键将以某种已知的方式舍入值以将相似的结果放入同一个桶……

      【讨论】:

      • 或者您可以使用自定义比较器来提供相同的功能,而无需自定义键,但使用小数。
      猜你喜欢
      • 2013-12-03
      • 1970-01-01
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多