我应该在字典中使用Decimal类型作为键吗?

5
我即将创建一个字典,每个值都有一个由实验计算得出的数字键。
我知道double和其他任何浮点类型都不适合用作键,因为很难比较两个浮点数的唯一性或相等性。
有人知道Decimal在这方面是否是一个好选择吗?另一种方法是将double转换为具有给定精度的字符串,但我认为这听起来像一个不优雅的解决方法。

3
为什么你想在字典中使用十进制数字作为键?这可能有助于我们为您提供最佳解决方案。 - Cédric Bignon
我的仪器为输入角度列表中的每个项目返回一个列表。因此,域自然映射将是一个字典,其中每个键都是实数(在数学意义上)。这个数字将用于计算,但大约六位数字的精度就足够了(仪器精度远低于此)。 - heltonbiker
好的,但为什么要用字典?字典的值是什么? - Cédric Bignon
这些值是照片中水平条纹图案投影的像素位置列表,每个条纹都与水平面成一定角度。 - heltonbiker
@CédricBignon 但说实话,我认为角度不是真正的输入,而是“条纹”或“浸润”对象的属性。也许我会重新制定我的实现,但“将数值作为字典键”的问题仍然是有效和相关的 :) - heltonbiker
我会将你的浮点数缩放为整数值。对于美元和美分,您需要乘以100并存储整数便士。如果您可以接受6位精度,请将您的浮点值乘以10^6。您可能需要引入公差值进行比较。如果您减去两个足够接近的值,则它们可能不必等于零,而是小于您的公差值。 - Beth
3个回答

6

在字典中使用floatdecimal作为键没有太大区别。两者都表示具有指数的数字 - 因此两者都会因不同的比较问题而受到影响,只是在不同的范围内。

如果您需要逐位相等的键,则可以使用任何一种方式,如果您需要用于“大约相同值”的键,则需要使用自定义键,该键将以某种已知方式舍入值以将类似结果放入同一个存储桶中...


1
或者您可以使用自定义比较器来提供相同的功能,而无需使用自定义键,但是可以包含小数。 - Gaute Løken

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;
}

在将浮点数存储到字典之前,我会使用这种方法对其进行量化。最大允许的相对误差可以通过常量来控制(目前为0.1%)。
PS:Mathf是Unity的类。它可以很容易地调整为使用标准的Math

1
如果您使用decimaldouble是因为int不够大,请考虑改用long
此外,我认为只要没有小数部分,且只包含整数(-1、0、1、2、3等),比较decimaldouble应该是可以的。
(尽管我不建议在比较重要时使用decimal/double,以避免未来出现意外错误。)
如果您只需要处理6位精度,则转换为int应该是可以的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接