我应该使用十进制类型作为字典中的键吗?

时间:2013-02-04 18:57:23

标签: c# .net dictionary key decimal

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

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

有谁知道Decimal在这方面是否是一个好的候选人?另一种方法是将double转换为具有给定精度的字符串,但这听起来像是一种不合理的解决方法。

3 个答案:

答案 0 :(得分:6)

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

如果你需要逐位相等的话,对于Dictionary要么是好的,如果你需要为“大约相同的值”键,你需要使它成为自定义键,它会以某种已知的方式对值进行舍入以将类似的结果放入同一桶...

答案 1 :(得分:1)

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

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

(虽然我不建议使用decimal / double比较,以避免任何未来的意外错误)

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

答案 2 :(得分: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