从浮点数度分秒1.40000中无损精度提取1度40分00.0秒的方法

news2024/11/25 3:38:10

那些最好的程序员不是为了得到更高的薪水或者得到公众的仰慕而编程,他们只是觉得这是一件有趣的事情!


从浮点数度分秒1.40000中无损精度提取1度40分00.0秒的方法

    • 🍀前言
    • 🌸传统的提取方法
      • 🔖算法介绍
      • 🧾Python源码
      • 📌小结
    • 🌿Python字符串截取提取
      • 🔖算法介绍
      • 🧾Python源码
      • 📌小结
    • 🍀无损精度的提取方法
      • 🔖算法介绍
      • 🧾Python源码
      • 📜C#源码
      • 📃Matlab源码
      • 📑C/C++源码
      • 📌小结
    • 🌹 结语
    • 📧Summary


📆Date: 2023年12月24日
🎬Author: 小 y 同 学
🔖Language: Python、C#、Matlab、C/C++


  将浮点数表示的度分秒1.40000进行无损精度的提取为1°40′00.0″,而不是1°39′99.9″。

🍀前言

  这是在《测量程序设计》这门课程所学习到的内容,在此十分地感谢老师分享的干货🌹

  在测量的角度表示方法中,为了记录和输入数据方便,通常会用类似ddd.mmsss的形式来表示角度ddd度mm分ss.s秒,例如将13度14分52.0秒表示为13.14520,那么如何在编程中正确的无精度的提取相应的度分秒成为了后续计算的首要且重要的问题,如果此步有误差,那么后续算法再精确、正确,也无法弥补

  本文将以1.40000和13.14520的提取为例,从传统的提取方法、Python字符串截取提取的方法以及无损精度的提取方法这三种方法进行比较介绍。对于前两种方法提供Python源码,对于无损精度提取方法提供Python、C#、Matlab、C/C++源码

🌸传统的提取方法

  这是网页上、以及一些书籍介绍的方法,之前一直没有发现问题,直到亲眼看到老师调试**1.40000被提取成1°39′99.9″**时,恍然大悟,实际运用中会有很大的问题!

🔖算法介绍

  通过直接对原始数据进行取整移动小数点的操作从而实现功能,流程描述如下:

  1. 对13.14520进行取整,这样便得到了度13。
  2. 将13.14520减去度的部分,同时乘100使得小数点右移两位变成14.520,再次进行取整,得到分14。
  3. 将14.520减去分的部分,得到秒52.0;提取结束。

🧾Python源码

def DMSToDMSError(dmsAngle: float) -> list:
    d = int(dmsAngle)
    m = int((dmsAngle - d) * 100)
    s = (dmsAngle - d - m / 100) * 10000
    return [d, m, s]


if __name__ == '__main__':
    a = 1.40000
    print(DMSToDMSError(float(a)))
    b = 13.14520
    print(DMSToDMSError(float(b)))  

运行效果:

传统方法提取

  可以看出提取出现了误差,需要注意的是:Python中整数与整数运算是可以得到小数结果的,可以使用//进行整除,也可以使用int函数进行一个转换。


📌小结

  这种提取方式在一般测试数据时可能不会出现问题,但是对于1.40000会被提取成1°39′99.9″,在秒位上多出了约40秒(外业测量员两行泪😭)。

  这是由于计算机内部存储采用二进制来存储,对于浮点数会有精度损失问题,这也是编程中不能直接对浮点数用==来对浮点数进行直接比较的原因

🌿Python字符串截取提取

🔖算法介绍

  这是笔者初学Python惯用的方法(太方便啦🤩),流程描述如下:

  1. 将浮点数13.14520使用格式化转为字符类型"13.1452000000"。
  2. 将字符串调用.split()方法按照"."进行分割,变为列表[“13”,“14520”]。
  3. 列表的0号元素即为度,用int函数转换即可。
  4. 列表的1号元素前两个字符组合是分,字符串截取int转换即可。
  5. 列表的1号元素余下字符组合是秒,需要注意的是秒是浮点类型,此处将余下部分"520"前两位"52"+“.”+余下部分"520"的剩余的字符"0"组成新字符"52.0",使用float函数转换即可;提取结束。

🧾Python源码

def DMSToDMS2(dmsAngle: float) -> list:
    dmsAngleStr = f"{dmsAngle:.10f}"
    (D, MS) = dmsAngleStr.split('.')  # 以小数点为分隔符,第一个为D,第二个为MS
    M = MS[0:2]  # MS的前两个字符是M
    S1 = MS[2:4]  # MS的其余字符是S,其中前两位是整数部分
    S2 = MS[4:]  # MS的其余字符是S,余下是小数部分
    return [int(D), int(M), float(S1 + '.' + S2)]


if __name__ == '__main__':
    a = 1.40000
    print(DMSToDMS2(a))
    b = 13.14520
    print(DMSToDMS2(b))

运行效果:

Python字符串截取提取


📌小结

  这种提取方法目前笔者还没遇到问题,对1.40000也可以做到无损精度提取,但是针对一些其他编程语言,难以或没有对字符串截取的操作、数据类型间的转换,将无法满足需求,算法对编程语言的通用性较差!

🍀无损精度的提取方法

🔖算法介绍

  与传统方法类似,但是不直接对原始数据进行操作,而是先将原始数据乘10000得到14000.0,再对整数部分提取即可避免1.39999…的问题。流程描述如下:

  1. 将原始数据13.14520乘10000得到131452.0。
  2. 将131452.0取整得到整数部分131452。
  3. 对131452除以10000随后取整得到度13。
  4. 将131452减去度的部分得到1452,除以100随后取整,得到分14。
  5. 131452.0减去度的部分、分的部分,得到秒52.0;提取结束。

🧾Python源码

def DMSToDMS(dmsAngle: float) -> list:
    dmsAngle *= 10000
    sAngle = int(dmsAngle)
    d = int(sAngle / 10000)
    m = int((sAngle - d * 10000) / 100)
    s = dmsAngle - d * 10000 - m * 100
    return [d, m, s]


if __name__ == '__main__':
    a = 1.40000
    print(DMSToDMS(float(a)))
    b = 13.14520
    print(DMSToDMS(float(b)))

运行效果:

Python无损精度提取


📜C#源码

using System.Net;

namespace DMSToDMS
{
    internal class Program
    {
        static (int d, int m, double s) DMSToDMS(double dmsAngle)
        {
            dmsAngle = dmsAngle * 10000;
            int sAngle = (int)dmsAngle;
            int d = sAngle / 10000;
            int m = (sAngle - d * 10000) / 100;
            double s = dmsAngle - d * 10000 - m * 100;
            return (d, m, s);
        }
        static void Main(string[] args)
        {
            double a = 1.40000;
            double b = 13.14520;
            double c = 13.14521;
            Console.WriteLine(DMSToDMS(a));
            Console.WriteLine(DMSToDMS(b));
            Console.WriteLine(DMSToDMS(c));
        }
    }
}

运行效果:

C#无损精度提取


📃Matlab源码

% 无损精度提取度分秒函数
function dms = DMSToDMS(dmsAngle)
    dmsAngle = dmsAngle * 10000;
    sAngle = fix(dmsAngle);
    d = fix(sAngle/10000);
    m = fix((sAngle - d * 10000)/100);
    s = dmsAngle - d * 10000 - m * 100;
    dms = [d, m, s];
end
% 调用无损精度提取度分秒函数
dms=DMSToDMS(1.40000)
dms=DMSToDMS(13.14520)
dms=DMSToDMS(13.14521)

运行效果:

Matlab无损精度提取


📑C/C++源码

#include<iostream>
using namespace std;

typedef struct 
{
	int d,m;
	double s;
}DMSAngle;

void DMSToDMS(double dmsAngle, DMSAngle* dms)
{
    dmsAngle = dmsAngle * 10000;
    int sAngle = (int)dmsAngle;
    dms->d = sAngle / 10000;
    dms->m = (sAngle - dms->d * 10000) / 100;
    dms->s = dmsAngle - dms->d * 10000 - dms->m * 100;
}

int main() {
    double a = 1.40000,b= 13.14520, c=13.14521;
    DMSAngle dmsAngle_a;
    DMSToDMS(a, &dmsAngle_a);

    DMSAngle dmsAngle_b;
    DMSToDMS(b, &dmsAngle_b);

    DMSAngle dmsAngle_c;
    DMSToDMS(c, &dmsAngle_c);

    cout<<dmsAngle_a.d<<" "<<dmsAngle_a.m<<" "<<dmsAngle_a.s<<endl;
    cout<<dmsAngle_b.d<<" "<<dmsAngle_b.m<<" "<<dmsAngle_b.s<<endl;
    cout<<dmsAngle_c.d<<" "<<dmsAngle_c.m<<" "<<dmsAngle_c.s<<endl;
    return 0;
}

运行效果:

C/C++无损精度提取


📌小结

  此方法比较巧妙,区别绝大部分网页、包括一些书籍资料中的传统的错误方法,可做到无损精度提取,且不受编程语言限制,值得推荐!

🌹 结语

  1. 值得注意的是:在Python3、Matlab等适合科学计算的编程语言中,整数与整数相运算的结果仍然为小数(与想象中的一致);但是在C#、C/C++包括Python2这类编程语言中,整数与整数相运算的结果将会被截断取整,例如3/2将会得到1,而不是1.5,可以采用3/2.0的方式来避免;这也是编程中常常会遇到的小bug。
  2. 由此也可以引发思考🤔或许有些算法我们在设计的适合毫无问题,而在实现的时候因为这些小细节而出现误差呢?
  3. 含注释的源码已托管于Github仓库,关注下方公众号回复关键字"231224"获取~
  4. 再次感谢授课老师给予的干货🌹🌹🌹

📧Summary

  有兴趣一起学习编程的小伙伴可以私聊小y一起学习,小y在Python,c/c++,C#和matlab语言上均有一定的基础😜😜😜


  • 路虽远,行则将至;事虽难,做则必成。希望认真学习的你能够有所收获~
  • 如果本文有幸可以帮到您,欢迎您的点赞、收藏与关注;您的点赞、收藏与关注是我创作的最大动力~

微信公众号

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java研学-HTTP 协议

一 概述 1 概念和作用 概念&#xff1a;HTTP 是 HyperText Transfer Protocol (超文本传输协议)的简写&#xff0c;它是 TCP/IP 协议之上的一个应用层协议。简单理解就是 HTTP 协议底层是对 TCP/IP 协议的封装。   作用&#xff1a;用于规定浏览器和服务器之间数据传输的格式…

(企业 / 公司项目)如何使用分布式任务调度框架Quartz集成 和 SpringBoot自带的定时任务集成?

SpringBoot自带的定时任务 首先在你的微服务项目中创建一个新的模块&#xff0c;定时调度模块 pom.xml里面关联公共模块common的依赖其他不需要改变 然后启动类别删&#xff0c;启动项目是否报错&#xff0c;写一个简单的测试类访问路径是否成功 package com.jiawa.train.bat…

力扣日记12.24-【二叉树篇】236. 二叉树的最近公共祖先

力扣日记&#xff1a;【二叉树篇】236. 二叉树的最近公共祖先 日期&#xff1a;2023.12.24 参考&#xff1a;代码随想录、力扣 ps&#xff1a;提前祝 平安夜快乐&#xff01; 236. 二叉树的最近公共祖先 题目描述 难度&#xff1a;中等 给定一个二叉树, 找到该树中两个指定节点…

nodejs+vue+ElementUi摄影作品图片分享工作室管理系统

第1周 2.21&#xff5e;2.27 查阅资料&#xff0c;学习vscode开发平台和vue框架技术 第2周 2.28&#xff5e;3.6 对软件功能需求进行分析, 软件功能模块划分及软件界面设计 第3周 3.7&#xff5e;3.13 撰写并提交毕业设计开题报告、英文资料翻译 第4周 3.14&#xff5…

[Linux] MySQL数据库之索引

一、索引的相关知识 1.1 索引的简介 索引是一个排序列表&#xff0c;包含索引值和包含该值的数据行的物理地址&#xff08;类似于 c 语言链表&#xff0c;通过指针指向数据记录的内存地址&#xff09;。 使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索…

Linux环境变量剖析

一、什么是环境变量 概念&#xff1a;环境变量&#xff08;environment variables&#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;是在操作系统中一个具有特定名字的对象&#xff0c;它包含了一个或多个应用程序所将使用到的信息&#xff0c…

excel统计分析——S-W正态性检验

参考资料&#xff1a; [1]马兴华,张晋昕.数值变量正态性检验常用方法的对比[J].循证医学,2014,14(02):123-128. 统计推断——正态性检验&#xff08;图形方法、偏度和峰度、统计&#xff08;拟合优度&#xff09;检验&#xff09;_sm.distributions.ecdf-CSDN博客 【统计学】…

Linux操作系统基础 – 修改文件权限

Linux操作系统基础 – 修改文件权限 Linux Operating System Essentials - Modify File Rights By JacksonML 文件是Linux操作系统存储信息的基本结构。文件是一组信息的集合。 在Linux操作系统和Windows操作系统相比较的最大不同&#xff0c;是Linux文件没有扩展名&#xff…

2023年全球前端大技术大会(GMTC北京站2023)-核心PPT资料下载

一、峰会简介 大会以“业务至上&#xff0c;效率为王”为主题&#xff0c;策划了 1 个主会场&#xff0c;10 个技术专场。会议议题包含前端 DevOps 实践、低代码、大前端监控、跨端技术选型、团队可持续发展、IoT 动态应用开发、移动端性能与效率优化、TypeScript、大前端技术…

等腰三角形两底角相等

等腰三角形定义: 是指至少有两边相等的三角形。相等的两个边称为这个三角形的腰 二.证明 有等腰△ABC,AB和AC是腰,p是BC的中点 证明等腰三角形两底角相等 即 ∠ A B P ∠ P C A ∠ABP∠PCA ∠ABP∠PCA ∴ ∴ ∴ 三角形内角和为180 ∵ { ∠ A B P ∠ A P B ∠ B A P 180 …

形态学处理

形态学处理的相关内容 &#xff08;1&#xff09;基于图像形态进行处理的一般方法 &#xff08;2&#xff09;这些处理方法基本是对二进制图像进行处理 &#xff08;3&#xff09;卷积核决定着图像处理后的结果 形态学图像处理 &#xff08;1&#xff09;腐蚀&#xff08;…

如何打包鸿蒙应用并发布到应用市场

知识点&#xff1a; HarmonyOS 应用打包后的文件为.app 格式&#xff0c; android 打包后的文件为.apk&#xff0c;IOS 打包后的文件为.apa HarmonyOS通过数字证书&#xff08;.cer文件&#xff09;和Profile文件&#xff08;.p7b文件&#xff09;等签名信息来保证应用的完整性…

最常见的SQL报错注入函数(floor、updatexml、extractvalue)及payload总结

SQL报错注入是一种常见的SQL注入攻击方式&#xff0c;攻击者通过注入恶意代码&#xff0c;触发数据库的错误响应&#xff0c;并从错误信息中获取有用的信息。 下面介绍最常见的三个报错注入函数用法及payload总结&#xff1a; 1、floor() 使用floor报错注入&#xff0c;需要…

VS2020使用MFC开发一个贪吃蛇游戏

背景&#xff1a; 贪吃蛇游戏 按照如下步骤实现:。初始化地图 。通过键盘控制蛇运动方向&#xff0c;注意重新设置运动方向操作。 。制造食物。 。让蛇移动&#xff0c;如果吃掉食物就重新生成一个食物&#xff0c;如果会死亡就break。用蛇的坐标将地图中的空格替换为 #和”将…

[动态规划]完全背包问题及其优化

题目描述 有N种物品和一个容量为 V 的背包&#xff0c;每种物品都有无限件可用。 第 i 种物品的体积是Ci&#xff0c;价值是Wi。求解在不超过背包容量的情况下&#xff0c;能够获得的最大价值。 输入 第一行为两个整数N、V(1≤N,V≤10000)&#xff0c;分别代表题目描述中的物…

java 怎么读取文件创建时间?

Java读取文件创建时间的实现方法 在工作时候&#xff0c;我们有时候需要获取到文件的最后更新时间&#xff0c;根据最近更新时间&#xff0c;来处理其他业务。那么&#xff0c;在Java中&#xff0c;怎么获取到文件最后更新时间呢&#xff1f;接下来凯哥(个人号&#xff1a;凯哥…

教你应对Github最新的2FA二次验证! 无地区限制, 你的Github账户可能被封禁!

文章目录 2FA 定义2FA验证方法1 硬件令牌2.推送通知3.SMS 验证4 基于语音的身份验证 解决方案安装身份验证器的谷歌浏览器插件打开 github 的二维码&#xff0c;直接扫描 2FA 定义 双因素身份验证 (2FA) 是一种身份和访管理安全方法&#xff0c;需要经过两种形式的身份验证才能…

大数据----MapReduce实现统计单词

目录 一、简介二、实现单词统计数据准备编程MapReduceJob 三、运行四、结果 一、简介 Hadoop MapReduce 是一个编程框架&#xff0c;它可以轻松地编写应用程序&#xff0c;以可靠的、容错的方式处理大量的数据(数千个节点)。 正如其名&#xff0c;MapReduce 的工作模式主要分…

每日一题——Leetcode908

方法一 数学思想&#xff1a; 其实就是看数组中最大值和最小值一个加上k一个减去k是否能刚好凑到0&#xff0c;如果不能就是两者之差 var smallestRangeI function(nums, k) {var min9999,max-1for(var i0;i<nums.length;i){min Math.min(min,nums[i])max Math.max(max…

Python数据分析 Matplotlib篇 基本方法初识 (第1讲)

Python数据分析 Matplotlib篇(第1讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…