可靠地使用双精度作为std :: map键 [英] Reliably using doubles as std::map keys

查看:201
本文介绍了可靠地使用双精度作为std :: map键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的同事之一最近提出了一个有趣的技巧,可靠地使用浮点数字作为C ++中的 std :: map 之类的键。



假设您想要处理某些浮点值(例如 price ),并且您知道这些值可以只有在代表实数时才使用离散值(例如,以某个 ticksize 的间隔),然后以下代码段可靠地将输入 / code>到 long long 价格

 双重价格,ticksize; //在其他地方初始化
long long priceKey = 0;

if((price / ticksize)<(ticksize / 2)){
priceKey =(long long)(price / ticksize);
} else {
priceKey =(long long)((price / ticksize)+(ticksize / 2));
}

例如,如果 price = 98.05 ticksize = 0.05 ,那么我们最终得到以下结果:

 code> price / ticksize = 1960.9999999999998 
ticksize / 2 = 0.025
priceKey =(long long)1960.9999999999998 + 0.025 = 1961

priceKey 可以继续用于像 std :: map< long long,order_t> 可靠地检索特定价格水平的订单。



是否有任何这种逻辑失败的情况? / strong>我试图为自己提供一个证明,为什么这可以工作,但我不认为我有足够的浮点运算经验来解释它。

解决方案

首先,您不应该除以 ticksize ,您应该乘以 ticksize ,可能会正确地表示为 double con留下您描述的应用程序。在这个例子中,这个倒数将是 20.0



其次,您可以使转换稍微简单一些,在我看来因此,更可读:



乘以价格 ticksize ,从double到最接近的整数,作为一个 long long (function llround )或作为 double (function nearbyint )。没有固有的原因,您不应该使用 double 作为 std :: map 的键,只要你使用兼容的哈希和相等函数(哈希函数应该为+0返回相同的哈希值和-0。如果等于 == ,可能你不应该如果您使用 == 作为平等,则使用NaN作为关键字。



在代码中:

  priceKey = llround(price * inverseticksize); 


One of my coworkers recently brought up an interesting trick to reliably use floating point numbers as keys in something like a std::map in C++.

Assuming you want to case on some floating point value (like price), and you know that these values can only take on discrete values despite representing real numbers (say, at intervals of a certain ticksize), then the following code snippet reliably converts an input price to a long long price key:

double price, ticksize; // Initialized elsewhere
long long priceKey = 0;

if ((price / ticksize) < (ticksize / 2)) {
    priceKey = (long long) (price / ticksize);
} else {
    priceKey = (long long) ((price / ticksize) + (ticksize / 2));
}

For example, if price = 98.05 and ticksize = 0.05, then we end up with the following result:

price / ticksize = 1960.9999999999998
ticksize / 2 = 0.025
priceKey = (long long) 1960.9999999999998 + 0.025 = 1961

priceKey could then go on to be used in something like a std::map<long long, order_t> to reliably retrieve orders at a particular price level.

Is there any case where such logic would fail? I tried working out a proof for myself of why this could work, but I don't think I have enough experience with floating point arithmetic to reason it out.

解决方案

First, you shouldn't divide by ticksize, you should multiply by the inverse of ticksize, which likely would be exactly representable as double considering the application you describe. This inverse would be 20.0 in your example.

Second, you can make the transformation slightly simpler and in my opinion more readable thus:

after multiplying price by the inverse of ticksize, round from double to the nearest integer, either as a long long (function llround) or as a double (function nearbyint). There is no inherent reason why you shouldn't use double as the key of std::map, as long as you use compatible hash and equality functions (the hash function should return the same hash for +0. and -0. if the equality is ==, and probably you shouldn't use NaN as key if you are using == as equality).

In code:

priceKey = llround(price * inverseticksize);

这篇关于可靠地使用双精度作为std :: map键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆