FastLight 2019-08-16 03:04 采纳率: 100%
浏览 599
已采纳

C语言开发中,sqlite 中的溢出整数如何能准确读取出来?

在sqlite中,有一个字段存储的是64位无符号整数。

小于 2^63-1 的数据都没问题,但是我们有大量超过此值的数据,比如 9223379502689557271,存到数据库里就变成了 -3.68861248304756E-311。

9223379502689557271 是 0x800006ca466e1b17,-3.68861248304756E-311 是一个精度不足(有效数字不足)的 0x800006ca466e1b17,我用数据库软件打开了这个数据库后,发现该浮点数的 hex 值依然是正确的,如图:(软件的十六进制展示是从右往左的)

图片说明

我尝试着用 sqlite3_column_blob sqlite3_column_int sqlite3_column_text 等方法去读取这个值,但是得到的数据都是 -3.68861248304756E-311,而且,这个值因为精度不足,无法还原成 9223379502689557271,我想请问大神们,既然数据库存储的原始数据是准确的,那么我该如何书写代码,才能将 9223379502689557271 或者 0x800006ca466e1b17 准确的读取出来呢?

  • 写回答

4条回答 默认 最新

  • FastLight 2019-08-16 14:40
    关注

    你们信么,我误打误撞把问题解决了!

    sqlite3_column_value 可以直接获取二进制数据,我直接从地址里获取数据了,获取到了如图所示的数据:(部分字节做了一下 & 255 操作)

    图片说明

    根据右边那一列标记来确定数据的位置,整数就在24-31字节,“浮点数”就在16-23字节,此问题完美解决,也谢谢各位回答的朋友了。

    代码奉上:

    char *key = NULL;
    int i = 0;
    
    key = sqlite3_column_value(stat, k);
    
                    if ((key[38] & 255) == 2) {
                        for (i = 23; i >= 16; --i) {
                            output = key[i] & 255;
    
                            if (output > 15) {
                                printf("%x", output);
                            }
                            else {
                                printf("0%x", output);
                            }
                        }
                    }
                    else {
                        for (i = 31; i >= 24; --i) {
                            output = key[i] & 255;
    
                            if (output > 15) {
                                printf("%x ", output);
                            }
                            else {
                                printf("0%x ", output);
                            }
                        }
                    }
    

    具体稳定性还有待观察,但是这是我目前能想到的唯一思路了。而且,对于 sqlite3_column_value 返回的数据结构我还尚不熟悉,熟悉后可能会有更高效的写法。

    ========== 2019-11-15 更新 ==========

    sqlite3_column_value 获取到的数据会受到sqlite.c版本影响,之前的代码是基于3.7.9写的,后来我将sqlite更新到3.29.0后,数据的位置变成了0-7字节,不区分整数型与浮点数型了。但是如果字段值本身是null,该处内存会保留上一条记录的数据,这会引起一些bug。好在8号字节有个标记,4和8为正常,1为异常的null(上一条数据的值),做下兼容判断就好。

    key = (char *) sqlite3_column_value(stmt, 1);
    
    if ((key[8] & 255) == 1) {
        // null,直接跳过
        continue;
    }
    
    for (i = 7; i >= 0; --i) {
        valueNum = key[i] & 255;
    
        if (valueNum > 15) {
            _snprintf(value, 32, "%x", valueNum);
        }
        else {
            _snprintf(value, 32, "0%x", valueNum);
        }
    
        strcat(record, value);
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 ubuntu系统下挂载磁盘上执行./提示权限不够
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误