python四舍五入(round精度不夠,有時不能實現四舍五入)


Python 所有文章傳送門
【Python】所有文章傳送門

目錄

  • 簡述 / 前言
  • 1. Python 實驗
  • 2. 自定義函數
  • 3. 總結

簡述 / 前言

最近心血來潮,剛復習到折半插入排序時,發現算法的mid(中間點)選擇的公式是:(low + high)/2,那么當(low + high)出現奇數時怎么辦呢,比如(low + high)/2 = 1.5,那么是取 1 還是 2 呢?于是我在 Python 中實驗了一下,由于 Python 中浮點數運算結果還是浮點數,因此我用了內置函數 round(number, ndigits) 來實現小數轉整數運算。

1. Python 實驗

>>> round(1.5, 0)
2.0

看樣子好像是四舍五入的取法,但是換了一個數字之后,就發現新大陸了!

>>> round(2.5, 0)
2.0

這個運算發現round其實就是直接截取了整數部分,那么事實果真如此嗎?文末會給出解答~

2. 自定義函數

第一反應就是官方的函數是不是有問題,于是找了幾篇博客(參考的一個博客解答,但并沒有完全解決)看看怎么回事,發現給出的解決方法都不能解決問題,實驗如下:

>>> from decimal import Decimal
>>>
>>> print(round(Decimal("1.5"),0))
2
>>> print(round(Decimal("2.5"),0))
2
>>> print(Decimal("1.5").quantize(Decimal("0.")))
2
>>> print(Decimal("2.5").quantize(Decimal("0.")))
2

于是一股腦的自己花了十幾分鐘寫了一個函數來實現:

def round_Pro(number, ndigits):"""實現四舍五入:param number: 要四舍五入的數字:param ndigits: 要保留的位數:return: 以 float 形式輸出"""flag = ''       # 用于記錄 number 的正負性if number < 0:flag = '-'number_abs = abs(number)    # 一律采用正數的四舍五入進行操作number_abs_str = str(number_abs)if '.' in number_abs_str:       # 如果給的數字是小數的話integer = int(number_abs_str.split('.')[0])     # 數字的整數部分decimal_str = number_abs_str.split('.')[1]      # 數字的小數部分decimal_cnt = len(decimal_str)      # 小數位數if ndigits >= decimal_cnt:      # 如果要保留的小數位數 >= 整個小數位數,則直接輸出原數字return numberelse:       # 要保留的小數位數 < 整個小數位數,需要進行四舍五入judge_num = int(decimal_str[ndigits])   # 舍入位數字(根據此數字判斷是否需要進位)if ndigits == 0:    # 只保留整數decimal = 0     # 小數設為 0if judge_num >= 5:  # 如果小數第一位 > 5,則整數進一位integer += 1else:       # 保留指定小數位數decimal = int(decimal_str[:ndigits])        # 要保留的小數(直接截斷轉為整數,便于后續直接計算進位)decimal_cnt = len(decimal_str[:ndigits])    # 要保留的小數位數if judge_num >= 5:      # 如果判斷位(指定保留小數位數后一位的小數數字,比如:number=1.234,ndigits=2,那么判斷位就是數字"4") > 5decimal += 1        # 小數進一位if len(str(decimal)) > decimal_cnt:     # 如果進位導致小數位最高位也進位了integer += 1        # 整數部分也要進位decimal = str(decimal)[1:]      # 小數部分去掉最高位(由于進位多出來的數據)decimal = str(decimal)return float(flag + str(integer) + '.' + decimal)else:       # 給的數字是一個整數,直接輸出return number

測試如下:

print(round_Pro(2.9897, 5))
print(round_Pro(2.4497, 1))
print(round_Pro(2.4497, 0))
print(round_Pro(2.5597, 0))
print(round_Pro(2.5597, 10))
print(round_Pro(0, 0))
print(round_Pro(0, 10))
print(round_Pro(-1.5, 0))
print(round_Pro(-1.5, 1))
print(round_Pro(-1.56, 1))
print(round_Pro(-1.56, 2))
print(round_Pro(-1.999, 2))

輸出如下:

2.9897
2.4
2.0
3.0
2.5597
0
0
-2.0
-1.5
-1.6
-1.56
-2.0

寫完之后發現我的邏輯其實有點復雜(先轉為字符串進行分割,再分別轉成數字進行計算),于是又找找看有沒有其它的解決方法,因為我堅信我不可能是第一個遇到這種問題的人,于是很快發現了另一篇博客(能夠解決此問題的一篇博客),完全解決了這個問題,即用到一個庫:decimal,只保留整數就是 Decimal("1."),保留1位小數就是 Decimal(".1"),2位小數就是 Decimal(".01")Decimal(".89") 也是一樣的,本質就是看你給的字符串中小數占了多少位而已】。

>>> from decimal import Decimal
>>> print(Decimal(1.5).quantize(Decimal("1."), rounding="ROUND_HALF_UP"))
2
>>> print(Decimal(2.5).quantize(Decimal("1."), rounding="ROUND_HALF_UP"))
3

3. 總結

解決方法,使用第三方庫函數,格式是:Decimal(要進行四舍五入的數字).quantize(Decimal("保留多少位小數"), rounding="ROUND_HALF_UP")

>>> from decimal import Decimal
>>> num = 1.5
>>> print(Decimal(num).quantize(Decimal("1."), rounding="ROUND_HALF_UP"))
2

那么回到文章開頭提出的問題,round為什么不能進行四舍五入呢? 其實round本質就是四舍五入,但是由于我們的計算機存儲數字的精度有問題,才導致了這種情況發生:

>>> from decimal import Decimal
>>> print(Decimal(1.535))
1.5349999999999999200639422269887290894985198974609375
>>> print(Decimal(1.725))
1.725000000000000088817841970012523233890533447265625

詳見 python3 小數位的四舍五入(用兩種方法解決round 遇5不進),文中給出了兩種解決方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17625.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17625.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17625.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于VMware安裝Linux虛擬機

1.準備Linux環境 首先&#xff0c;我們要準備一個Linux的系統&#xff0c;成本最低的方式就是在本地安裝一臺虛擬機。為了統一學習環境&#xff0c;不管是使用MacOS還是Windows系統的同學&#xff0c;都建議安裝一臺虛擬機。 windows采用VMware&#xff0c;Mac則采用Fusion …

使用Spring Boot編寫的小項目

加法計算器 前端代碼 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…

若依跳轉(新增)頁面,在菜單中不顯示的頁面

在router.js文件中 跳轉方式 this.$router.push(/monitor/b/b)

有限元之有限元法的實現

目錄 一、單元剛度矩陣及單元荷載 二、總剛度矩陣及總荷載的合成 三、邊界條件處理 四、算例實現 4.1 C代碼 4.2 計算結果 五、結論 前三節我們介紹了有限元的基本概念、變分理論及有限元空間的構造&#xff0c;本節我們探討如何實現有限元法。我們繼續以二維橢圓型方程…

以太坊現貨ETF獲批:引發ETH價格暴漲,市場熱議達到高潮

2024年5月24日&#xff0c;北京時間&#xff0c;以太坊現貨ETF正式獲得美國證券交易委員會&#xff08;SEC&#xff09;的批準&#xff0c;成為繼比特幣之后&#xff0c;美國主權政府承認的又一加密貨幣基金產品。這一意外的利好消息引發了加密貨幣市場的狂歡&#xff0c;以太坊…

JavaWeb開發 2.Web開發 Web前端開發 ①介紹

內心一旦平靜&#xff0c;外界便鴉雀無聲 —— 24.5.27 一、初識Web前端 網頁有哪些部分組成? 文字、圖片、音頻、視頻、超鏈接 ...網頁&#xff0c;背后的本質是什么? 前端代碼前端的代碼是如何轉換成用戶眼中的網頁的? 通過瀏覽器轉化(解析和渲染)成用戶看…

dx11硬件解碼傳遞給opencl并行處理

directx11 解碼 使用ffmpeg進行directx11 解碼 將解碼后的NV12格式數據從D3D11 Texture中通過OpenCL處理需要經過幾個步驟&#xff1a;首先&#xff0c;確保D3D11 Texture正確設置并與OpenCL上下文關聯&#xff1b;然后&#xff0c;將NV12數據分兩個步驟處理&#xff08;Y平面…

調試面對面翻譯小程序

調試面對面翻譯小程序 文章目錄 調試面對面翻譯小程序預覽1.拉取項目2.在微信開發者工具打開使用 微信版本要求微信同聲傳譯插件支持功能 此demo用于學習 預覽 1.拉取項目 git clone https://github.com/Tencent/Face2FaceTranslator或者&#xff08;加速鏡像&#xff09; git …

Warning: Each child in a list should have a unique “key“ prop.

問題描述&#xff1a; 使用ProTable的時候&#xff0c;報錯如下 原因分析&#xff1a; 根據報錯內容可以分析出&#xff0c;表格數據缺少唯一key&#xff0c; <PaginationTablecolumns{columns}pagination{{pageSize: 10,current: 1,showSizeChanger: true,showQuickJum…

kafka 可以脫離 zookeeper 單獨使用嗎?為什么?

Kafka是一個分布式的流式處理平臺&#xff0c;它依賴于Zookeeper來管理集群元數據、選舉Leader以及故障恢復。在Kafka集群中&#xff0c;Zookeeper負責保存和維護分布式系統的信息。 雖然理論上可以將Kafka與Zookeeper分開&#xff0c;但實際上&#xff0c;Kafka在設計時就與Z…

JavaScript中的相等操作符(== vs ===)選擇指南

在使用JavaScript進行比較時,我們經常會遇到相等操作符 == 和嚴格相等操作符 ===。本文將深入探討這兩者之間的區別,并說明在何種情況下應使用 === 而不是 ==。 相等操作符(==) 相等操作符 == 會在進行比較之前對其兩個操作數進行必要的類型轉換。這意味著即使兩個操作數…

網絡安全行為可控定義以及表現內容簡述

在數字化快速發展的今天&#xff0c;網絡安全已成為國家和企業不可或缺的防線。據統計&#xff0c;網絡攻擊事件頻發&#xff0c;給全球經濟帶來了巨大損失。因此&#xff0c;確保網絡安全行為可控顯得尤為重要。今天我們來聊聊網絡安全行為可控定義以及表現內容。 網絡安全行為…

摸魚大數據——Hive表操作——分區表

1、介紹 特點: 分區表會在HDFS上產生目錄。查詢數據的時候使用分區字段篩選數據&#xff0c;可以避免全表掃描&#xff0c;從而提升查詢效率 注意: 如果是分區表&#xff0c;在查詢數據的時候&#xff0c;如果沒有使用分區字段&#xff0c;它回去進行全表掃描&#xff0c;會降低…

說一下 ACID 是什么?

ACID 是數據庫事務的四個特性的首字母縮寫&#xff0c;包括原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔離性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09;。 原子性&#xff08;Atomicity&…

什么是NAND Flash ECC?

在存儲芯片行業&#xff0c;數據完整性和可靠性是至關重要的。為了確保數據的準確性和防止數據丟失&#xff0c;ECC&#xff08;錯誤校正碼&#xff09;在NAND Flash存儲中扮演了關鍵角色。MK米客方德將為您解答NAND Flash ECC的基本概念、工作原理及其在實際應用中的重要性。 …

重繪和重排

重繪&#xff08;Repaint&#xff09;和重排&#xff08;Reflow&#xff09;是與網頁渲染和布局密切相關的兩個概念。以下是關于這兩個概念的詳細解釋&#xff1a; 重繪&#xff08;Repaint&#xff09; 定義&#xff1a; 當一個元素的外觀發生改變&#xff0c;但沒有改變布…

C#【進階】俄羅斯方塊

俄羅斯方塊 文章目錄 Test1_場景切換相關BeginScene.csBegionOrEndScene.csEndScene.csGame.csGameScene.csISceneUpdate.cs Test2_繪制對象基類和枚舉信息DrawObject.csIDraw.csPosition.cs Test3_地圖相關Map.cs Test4_坐標信息類BlockInfo.cs Test5_板磚工人類BlockWorker.…

數據庫中字符串相加需要換行

數據庫中字符串相加需要換行&#xff0c;這個需求在現在項目中很常見&#xff0c;特別是備注內容的追加&#xff0c;因此把Oracle/SQLServer/MySQL這幾種數據庫的使用進行簡單的總結一下 1、本文內容 Oracle中實現字符串相加需要換行SQLServer中實現字符串相加需要換行MySQL中…

VMware的網絡不通?這一篇給你一定的參考.虛擬機網絡配置

如果你的虛擬機莫名其妙ping不通網絡了&#xff0c;可以參考一下我的配置。這不是一篇教程&#xff0c;你可以核對一下自己的bug。 虛擬網絡配置器中&#xff1a; 使用管理員權限更改設置&#xff0c;會跳出來vmnet0 橋接、僅主機和NAT都必須要有 vment0&#xff1a; vmnet1:…

【樂吾樂3D可視化組態編輯器】相機與視角

系統默認的相機為環繞旋轉相機&#xff0c;它可以環繞一個中心點做上下左右的旋轉&#xff0c;來從不同角度觀察場景。當然&#xff0c;您也可以把一些特定角度的信息保存下來&#xff0c;在系統中我們把這個信息稱作視角。通過交互中的切換視角動作&#xff0c;您就可以實現把…