平台:x86_64

结论:Zset的最大分数不要超过18014398509481982(17位数字,54位二进制),否则不会得到期望的值。

REdis:5.0.4

Zset采用double存储分数值(score),而incrbyfloat和hincrbyfloat采用的是long double存储数值。

double本身是可以存储比18014398509481982(17位数字,54位二进制)大的值,比如18014398509481983(也是17位数字,54位二进制)。但REdis在返回结果时,调用strtod将值转成double类型。

取值源代码:

double zzlGetScore(unsigned char *sptr) { // t_zset.c:722

unsigned char *vstr;

unsigned int vlen;

long long vlong;

char buf[128];

double score;

serverAssert(sptr != NULL);

serverAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));

if (vstr) {

memcpy(buf,vstr,vlen);

buf[vlen] = '\0';

// 调用库函数strtod,

// 如果值小于18014398509481983,能得到预期的值,

// 否则总是返回18014398509481984(2的54次方)。

score = strtod(buf,NULL); // 字符串转double

} else {

score = vlong;

}

return score;

}

以字符串形式返回:

/* Add a double as a bulk reply */

void addReplyDouble(client *c, double d) { // networking.c:471

char dbuf[128], sbuf[128];

int dlen, slen;

if (isinf(d)) {

/* Libc in odd systems (Hi Solaris!) will format infinite in a

* different way, so better to handle it in an explicit way. */

addReplyBulkCString(c, d > 0 ? "inf" : "-inf");

} else {

dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d); // double转字符串

slen = snprintf(sbuf,sizeof(sbuf),"$%d\r\n%s\r\n",dlen,dbuf);

addReplyString(c,sbuf,slen);

}

}

x86_64上的测试:

127.0.0.1:6379> del k1

(integer) 1

127.0.0.1:6379> zadd k1 18014398509481982 m1

(integer) 1

127.0.0.1:6379> zrange k1 0 -1 WITHSCORES

1) "m1"

2) "18014398509481982" 预期的值

127.0.0.1:6379> del k1

(integer) 1

127.0.0.1:6379> zadd k1 18014398509481983 m1

(integer) 1

127.0.0.1:6379> zrange k1 0 -1 WITHSCORES

1) "m1"

2) "18014398509481984" 非预期的值(和strtod相关)

127.0.0.1:6379> del k1

(integer) 1

127.0.0.1:6379> zadd k1 18014398509481982 m1

(integer) 1

127.0.0.1:6379> zrange k1 0 -1 WITHSCORES

1) "m1"

2) "18014398509481982" 预期的值

127.0.0.1:6379> zincrby k1 1 m1

"18014398509481984" 非预期的值

127.0.0.1:6379> zrange k1 0 -1 WITHSCORES

1) "m1"

2) "18014398509481984" 非预期的值

附:C/C++浮点知识图谱

REdis zset和double的更多相关文章

  1. 实现排行榜神器——redis zset

    需求:假如现在需要搞个 “运动消耗卡路里排行榜”,例似微信步数排名,显示排名前20人的信息和消耗的卡里路,怎样实现排序? 一般思路:存储信息,然后数据库查询,排序?(假如有几十万人参与排名,这样查my ...

  2. 延时任务-基于redis zset的完整实现

    所谓的延时任务给大家举个例子:你买了一张火车票,必须在30分钟之内付款,否则该订单被自动取消.订单30分钟不付款自动取消,这个任务就是一个延时任务. 我之前已经写过2篇关于延时任务的文章: <完 ...

  3. Redis ZSet 有序集合

    有序集合类型与集合类型的区别就是他是有序的.有序集合是在集合的基础上为每一个元素关联一个分数,这就让有序集合不仅支持插入,删除,判断元素是否存在等操作外,还支持获取分数最高/最低的前N个元素.有序集合 ...

  4. redis zset底层实现原理

    一.Zset编码的选择 1.有序集合对象的编码可以是ziplist或者skiplist.同时满足以下条件时使用ziplist编码: 元素数量小于128个 所有member的长度都小于64字节 其他: ...

  5. Redis ZSet Type

    Redis有序集合的操作命令和对应的api如下: zadd [zset] sco 'value' JedisAPI:public Long zadd(final String key, final d ...

  6. 将mysql表数据批量导入redis zset结构中

    工作中有这样一个需求,要将用户的魅力值数据做排行,生成榜单展示前40名,每隔5分钟刷新一次榜单.这样的需求用redis的zset是很方便实现的.但是数据存在mysql的表中,有400多万条,怎么将其快 ...

  7. Redis学习第六课:Redis ZSet类型及操作

    Sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素时候可以指定,每次指定后,zset会自动重新按新的值调整顺序.可以理解为有两列字段的数据表,一列 ...

  8. (PHP)redis Zset(有序集合 sorted set)操作

    /** * * Zset操作 * sorted set操作 * 有序集合 * sorted set 它在set的基础上增加了一个顺序属性,这一属性在修改添加元素的时候可以指定,每次指定后,zset会自 ...

  9. C# 通过ServiceStack 操作Redis——ZSet类型的使用及示例

    Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列 /// <summary> /// Sorted Sets是将 ...

随机推荐

  1. Day04 -玩弄Ruby的方法:instance method与class method

    前情提要在第三天时,我们解说了如何在class里用include与extend,去使用module的method. Include is for adding methods to an instan ...

  2. tensorflow object detection api graph rewriter

    目前,tensorflow 目标识别的api函数可以使用 graph rewriter这样的配置,这样配置的引入主要是为了模型压缩使用,具体设置参数有: syntax = "proto2&q ...

  3. (1234队)NABCD分析

    1.N(需求) 我们通过平常上自习时发现的问题和在校调查发现人们在寻找空教室上自习时会遇到诸多问题,其中 问题一:找不到空教室:5% 问题二:非上课教室学生太多:70% 问题三:有占座情况:20% 问 ...

  4. day 09

    内存管理 引用计数:垃圾回收机制的依据 当变量的值被引用的时,变量值的引用计数+1,当变量名被解除绑定时该值的引用计数减少一. 当引用计数变成0的时候会被垃圾回收机制回收. 引用计数会出现循环引用问题 ...

  5. 解题(IdenticalTree--拓扑结构相同子树 )

    题目描述 对于两棵彼此独立的二叉树A和B,请编写一个高效算法,检查A中是否存在一棵子树与B树的拓扑结构完全相同. 给定两棵二叉树的头结点A和B,请返回一个bool值,代表A中是否存在一棵同构于B的子树 ...

  6. 通过.ibd和.frm恢复mysql数据

    背景:因为机器损坏,数据库的索引文件什么的都损坏了.只留下了一个mysql的data目录… 此方法恢复数据的前提:建表用的innodb索引   备注:如果mysql的目录还都在,可以先尝试,将mysq ...

  7. spring mvc 参数绑定

    基础类型 原始类型:id必须要传,否则报错. @RequestMapping("/test") @ResponseBody public ResponseData test(int ...

  8. AS报:Manifest merger failed with multiple errors, see logs

    * What went wrong:Execution failed for task ':app:processDebugManifest'. Manifest merger failed with ...

  9. Node.js的内存问题

    v8堆内存限制默认是1GB,所以可能成为瓶颈. 但是Buffer的内存不受限制,而且可以开多个Nodejs实例然后通过代理进行负载均衡,不过不知道这样效果怎么样呢? 但是基本上应该内存的话不会成为单实 ...

  10. 实时ETL

    传统的ETL通常采用批处理的方式,一般来说是每天的夜间进行,当天的数据要到第二天才可以获得.随着数据仓库技术的逐步成熟,企业对数据仓库时间延迟的要求更高,希望达到零延迟,也就出现了实时ETL. 实时E ...