【Android】SharedPreferences存储中没有 Double 类型数据存储的解决方式

项目需求

存储定位数据,需要保存到小数点后10位数据。

需求分析

项目需求看起来很简单,其实实现起来也不难,我们直接使用SharedPreferences 存储一下就好了,反正也没其他要求。

好了,直接使用SharedPreferences 存储一下double数据就行了,
但是,SharedPreferences 不能存储double数据????

。。。。。。

是的,SharedPreferences 就是不能存储double类型的数据,虽然double类型的数据也是基本类型数据。。。

SharedPreferences中存储的数据是以key/value键值对的形式保存在XML文件中,这些数据具有一定的类型限制。具体来说,SharedPreferences能够直接存储的数据类型包括:

  • String:字符串类型,用于存储文本信息。
  • int:整型,用于存储整数数据。
  • float:浮点型,用于存储小数数据。
  • long:长整型,用于存储比int类型范围更大的整数数据。
  • boolean:布尔型,用于存储真或假两种状态。
  • StringSet:字符串集合类型,用于存储一组字符串。

那我们的需求是要保存的数据有10位小数的,但是使用float存储的话这个精度也打不到我们的需求,float 类型大约能精确表示 6-9 位有效数字,其中小数部分通常不超过 7 位;而 double 类型大约能精确表示 15-17 位有效数字,其中小数部分通常不超过 15 位。

所以我们要是满足需求的话是要使用double的,那怎么解决这个问题呢。

解决方法

解决方法一

将 double 转换为 String

// 存储 double
SharedPreferences sharedPreferences = context.getSharedPreferences("myPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
double myDouble = 12.34;
editor.putString("myDoubleKey", String.valueOf(myDouble));
editor.apply();

使用的时候将一个 String 类型的带小数的数据转换为 double 类型,并保留10位小数。在这个过程中,可以使用 BigDecimal 来处理精度问题。

 public static double convertStringToDouble(String str) {try {// 将字符串转换为 BigDecimalBigDecimal bigDecimal = new BigDecimal(str);// 设置精度并进行舍入bigDecimal = bigDecimal.setScale(10, RoundingMode.HALF_UP);// 转换为 doublereturn bigDecimal.doubleValue();} catch (NumberFormatException e) {// 处理转换异常System.err.println("Invalid number format: " + str);return 0.0; // 或者根据需要返回其他值}}

解决方法二

将 double 值转换为 long

这看上去第一眼就懵逼了,不是,这个long能存小数吗?那肯定不能啊。

long 类型本身是整数,不能直接存储小数。但是,使用 long 来存储 double 值的关键在于如何处理它们的二进制表示。

首先我们要知道:

  • double 在内存中以 IEEE 754 格式表示,它包含了符号位、指数部分和尾数部分。

  • 这个表示可以被转换为一个 64 位的整数(long),通过 Double.doubleToRawLongBits() 方法。

  • 调用 Double.doubleToRawLongBits(value) 时,实际上是将 double 的内存表示(即二进制数)转换为一个 long 类型的数字。这并不是说 long 存储了小数,而是 long 存储了 double 的二进制表示。

  • 这个 long 数字可以被完整地还原为原始的 double 值。

浮点数的内存表示

double 类型在 Java 中使用 IEEE 754 标准进行表示。它包含:

  • 1 位符号位:表示正数或负数。
  • 11 位指数:用来表示数值的范围。
  • 52 位尾数(也称为有效数字):用于表示具体的数值。

这样,double 值的存储是通过这些位来表示其具体的数值特性。整个 double 在内存中占用 64 位(即 8 字节)。

使用 long 存储 double

由于 double 是 64 位的,而 long 也是 64 位的,可以利用这种大小的相同来存储 double 的原始位表示。具体流程如下:

存储过程
  • 转换:

当调用 Double.doubleToRawLongBits(value) 时,Java 将 double 值的 64 位二进制表示转换为一个 long 类型的数字。
这个 long 数字实际上是 double 值在内存中的“快照”,保留了所有的位信息。

  • 存储:

将得到的 long 数字存储到 SharedPreferences 中。

读取过程
  • 获取 long 值:

从 SharedPreferences 中读取之前存储的 long 值。

  • 还原:

使用 Double.longBitsToDouble(longBits) 方法将这个 long 值转换回原来的 double 值。

在这个过程中,Java 会重新解析这个 long 的位信息,将它解读为 double 的各个部分(符号位、指数、尾数),并计算出原始的浮点数值。


所以,假设我们有一个double数据3.14,使用SharedPreferences 存储这个数据时,我们要

转换 double 为 long

调用 Double.doubleToRawLongBits(value) 时,Java 会将 double 值的 64 位二进制表示转换为一个 long 类型的数字。这一过程包括以下几个步骤:

内部表示:

首先,Java 使用 IEEE 754 标准来表示 double 值。这个表示方式将 double 的数值分解为三部分:

  • 符号位(1 位):决定数值是正是负。
  • 指数部分(11 位):用于表示数值的范围和大小。
  • 尾数(有效数字)(52 位):表示实际的数值。

生成长整型:

Double.doubleToRawLongBits(value) 方法会将这些位拼接成一个 64 位的整数(long),这个整数就是 double 在内存中的原始二进制表示。

例如,对于 3.14,这个转换会生成一个特定的 long 值,表示 3.14 在 IEEE 754 中的位模式。

存储 long 到 SharedPreferences

得到了这个 long 值,就可以将其存储在 SharedPreferences 中:

long bits = Double.doubleToRawLongBits(value);
sharedPreferences.edit().putLong("key", bits).apply();

获取 long 值

需要读取存储的 double 值时,首先从 SharedPreferences 中获取之前存储的 long 值:

long bits = sharedPreferences.getLong("key", 0);

还原 long 为 double

将这个 long 值转换回原始的 double 值,使用 Double.longBitsToDouble(longBits) 方法:

double value = Double.longBitsToDouble(bits);

解析过程:
在这一过程中,Java 会根据 long 中的位信息重新构造出 double 的三个组成部分:

  • 符号位:如果符号位为 0,则表示正数;如果为 1,则表示负数。
  • 指数部分:根据存储的位值,Java 会计算出实际的指数。
  • 尾数:有效数字也会根据存储的位值重新构造出来。

这个过程会将 long 的二进制位解析成 double 需要的各个部分,然后合成最终的浮点数值。

通过以上的步骤,Java 能够有效地将 double 类型的数值以其原始二进制格式存储为 long 类型,从而在 SharedPreferences 中安全地保存和读取。这个方法不仅确保了数据的准确性,还利用了 long 和 double 相同的存储大小(64 位),使得转换过程既高效又简便。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/467227.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 热题 100之 堆

1.数组中第k个最大元素 和Acwing 786 第k个数一模一样 排序 思路分析1:此题要求时间复杂度未为O(n)。虽然库函数sort和快速排序都能过,但是时间复杂度不满足条件。下面优化快速排序,写一个快速选择算法。我们可以引入随机化来加速这个过程&…

redis笔记-数据结构

zset zset一方面它是一个 set,保证了内部value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。 zset的底层是由字典和跳表实现。 字典主要用来存储value和score的对应关系。跳表这个数据结构主要用来提…

day20-21之间的项目实战:若依ruoyi开发(可以跳过)

一,项目概述 官网文档地址:http://doc.ruoyi.vip/ rouyi是一个后台管理系统,基于经典技术组合(spring boot,apache shiro,mybatis,thymeleaf)主要是让开发者注重专注业务&#xff0…

【Android】名不符实的Window类

1.“名不符实”的Window类 Window 是一个窗口的概念,是所有视图的载体,不管是 Activity,Dialog,还是 Toast,他们的视图都是附加在 Window 上面的。例如在桌面显示一个悬浮窗,就需要用到 Window 来实现。Wi…

SDL事件相关

文章目录 事件相关的函数和数据结构用户自定义事件代码相关: 事件相关的函数和数据结构 SDL_WaitEvent :等待一个事件SDL_PushEvent 发送一个事件SDL_PumpEvents(): 将硬件设备产生的时间放入事件队列 ,用于读取事件,在调用该函数之前&#…

机器人课程——使用TIA Portal V15博图软件进行西门子组态——带显示屏

一.打开TIA Portal V15博图软件创建项目 1.选择创建新项目 创建完成后选择PLC 二.创建完成后选择设备PLC (此处以S7-1200 1214FC DC/DC/DC 为例) 三.添加扩展板(如有——这里以223-1BL32-0XB0为例) 四.更改扩展版地址 五.添加触摸屏(这里以…

【数据集】【YOLO】【目标检测】道路结冰数据集 1527 张,YOLO目标检测实战训练教程!

数据集介绍 【数据集】道路结冰数据集 1527 张,目标检测,包含YOLO/VOC格式标注。数据集中包含2种分类:“clear_road, ice_road”。数据集来自国内外图片网站和视频截图,部分数据经过数据增强处理。检测范围监控视角检测、无人机视…

【Mysql NDB Cluster 集群(CentOS 7)安装笔记一】

Mysql NDB Cluster 集群(CentOS 7)安装笔记 NDB集群核心概念 NDBCLUSTER(也称为NDB)是一个内存存储引擎,提供高可用性和数据保存功能。 NDBCLUSTER存储引擎可以配置一系列故障转移和负载平衡选项,但从集群级别的存储引擎开始是最容易的。NDB集群的NDB存储引擎包含一整套…

利用京东API接口实现商品详情数据获取与表格化展示

在电商数据分析与运营过程中,获取商品详情数据是至关重要的一环。京东作为国内领先的电商平台,其开放平台提供了丰富的API接口,使得开发者能够高效地获取商品信息。本文将详细介绍如何通过京东API接口获取商品详情数据,并将其整理…

数据结构-并查集专题(1)

一、前言 因为要开始准备年底的校赛和明年年初的ACM、蓝桥杯、天梯赛,于是开始按专题梳理一下对应的知识点,先从简单入门又值得记录的内容开始,并查集首当其冲。 二、我的模板 虽然说是借用了jiangly鸽鸽的板子,但是自己也小做…

博奥龙/诊断原料抗体对

在ELISA中,抗体与抗原的结合精确度依赖于抗体的特异性和灵敏度。特异性较差的抗体可能导致显著的非特异性背景信号,而特异好但亲和力弱的抗体可能会被洗掉,从而产生假阴性数据。因此,选择合适的可避免交叉反应和确保检测结果的准确…

OceanBase详解及如何通过MySQL的lib库进行连接

OceanBase详解及如何通过MySQL的lib库进行连接 一、引言二、OceanBase概述1. 起源与发展2. 核心技术特点3. 应用场景三、OceanBase架构解析1. 系统架构2. 存储引擎3. 分布式架构四、如何使用MySQL的lib库连接OceanBase1. 前提条件2. 安装MySQL Connector/C3. 编写连接代码4. 编…

java导出word文件(手绘)

文章目录 代码细节效果图参考资料 代码细节 使用的hutool的WordUtil,WordUtil对poi进行封装,但是这一块的官方封装的很少,很多细节都没有。代码中是常见的绘制段落,标题、表格等常用api Word07Writer writer WordUtil.getWriter(…

RNN(循环神经网络)详解

1️⃣ RNN介绍 前馈神经网络(CNN,全连接网络)的流程是前向传播、反向传播和参数更新,存在以下不足: 无法处理时序数据:时序数据长度一般不固定,而前馈神经网络要求输入和输出的维度是固定的&a…

qt QHttpMultiPart详解

1. 概述 QHttpMultiPart是Qt框架中用于处理HTTP多部分请求的类。它类似于RFC 2046中描述的MIME multipart消息,允许在单个HTTP请求中包含多个数据部分,如文件、文本等。这种多部分请求在上传文件或发送带有附件的邮件等场景中非常有用。QHttpMultiPart类…

2-148 基于matlab的铣削动力学仿真

基于matlab的铣削动力学仿真,推导出指导加工的稳定性叶瓣图,并得到各主轴转速下对应的极限切深。输入不同方向刚度和切入角、切削力系数等参数,进行铣削动力学仿真。程序已调通,可直接运行。 下载源程序请点链接:2-14…

使用STM32F407xx的GPIO引脚实现跑马灯效果的详细步骤

1、使用Keil创建一个新工程 2、在弹出的对话框,填写工程的名字,例如工程名字为demo_led 3、为保存的工程,选择对应的芯片 4、为当前工程,添加相应的库函数 5、若库函数添加成功,则显示当前工程目录树 6、在当前工程目录…

_浅谈单片机的gcc优化级别__以双音频信号发生器为例

一、简介 gcc有多种优化级别,一般不选择的情况下,IDE默认是按照-Og或这-O2优化的。 以gcc编译器为例,浅谈一下优化级别,我们常见的优化一般是指gcc的-O2、-Og。除此之外,gcc还有-Os等一系列优化,链接器也有…

用JavaScript、Nodejs写一个本地tcp服务,用于前端WebSocket调试

效果: 准备工作: 新建一个文件夹,在根目录安装依赖: npm install ws express 依赖介绍: WS是一个轻量级、高效的WebSocket库,适用于Node.js环境。 express 是一个流行的Node.js Web应用程序框架。 新…

企业常见的主数据管理挑战及解决方案

在当今高度数字化的商业环境中,数据已成为企业决策、运营和战略规划的核心。主数据管理(MDM)作为管理核心业务数据的一种方式,帮助企业确保其关键数据在整个组织中保持一致、准确和可信。然而,许多企业在实施主数据管理…