• REdis zset和double


     

    平台:x86_64

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

    REdis5.0.4

     

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

     

    double本身是可以存储比1801439850948198217位数字,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] = '';

            // 调用库函数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 %s ",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++浮点知识图谱

     

  • 相关阅读:
    python基础26——派生&多态&绑定与非绑定方法
    python基础25——继承&属性查找&多继承的菱形问题&Mixins机制
    emmm......就当练习了系列20
    python基础24——封装&property
    emmm......就当练习了系列19
    python基础23——面向对象
    [转]N年Python老司机,血泪总结新手常见10大错误
    ATM机+购物车
    python基础22——logging模块&
    emmm......就当练习了系列18
  • 原文地址:https://www.cnblogs.com/aquester/p/10769827.html
Copyright © 2020-2023  润新知