自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

負數(shù)的絕對值居然還是負數(shù),你知道嗎?

開發(fā) 前端
“抽象泄漏”是軟件開發(fā)時,本應隱藏實現(xiàn)細節(jié)的抽象化不可避免地暴露出底層細節(jié)與局限性。抽象泄露是棘手的問題,因為抽象化本來目的就是向用戶隱藏不必要公開的細節(jié)。

發(fā)現(xiàn)問題

最近在處理一個線上問題時,遇到了非常奇怪的情況。

使用Math.abs(hash) % list.size()計算索引值時,竟然出現(xiàn)了負數(shù)!

看了下hash的值是-2147483648,恰好是Integer.MIN_VALUE。

按照絕對值的負負得正,結(jié)果應該是2147483648 % list.size(),結(jié)果是[0, list.size() - 1]。

但是結(jié)果是負的,這簡直讓人匪夷所思,難道Math.abs函數(shù)有問題嗎?

本著技術人的思維,事出反常必有妖,咱們今天就來抓一下這個妖。

分析問題

直接找源碼:

/**
 * Returns the absolute value of an {@code int} value.
 * If the argument is not negative, the argument is returned.
 * If the argument is negative, the negation of the argument is returned.
 *
 * <p>Note that if the argument is equal to the value of
 * {@link Integer#MIN_VALUE}, the most negative representable
 * {@code int} value, the result is that same value, which is
 * negative.
 *
 * @param   a   the argument whose absolute value is to be determined
 * @return  the absolute value of the argument.
 */
public static int abs(int a) {
    return (a < 0) ? -a : a;
}

代碼沒啥問題,數(shù)組小于0的時候,取反,大于等于0的時候,返回原值。

細心的已經(jīng)開始看注釋了。

官方注釋解釋了,如果參數(shù)是Integer.MIN_VALUE,返回的還是自身?,F(xiàn)象和描述相符,但是和代碼不符,按照代碼運行應該是-Integer.MIN_VALUE,負負得正。

玄機在哪呢?

沒錯,就是你想的那樣。

你答對了

越界了。

int類型占32位,數(shù)值范圍是[-2147483648, 2147483647]。-Integer.MIN_VALUE是2147483648,比Integer.MAX_VALUE的2147483647大,所以越界了。

在計算機系統(tǒng)中,數(shù)值一律用補碼來表示和存儲。使用補碼的主要優(yōu)點是可以將符號位和數(shù)值位統(tǒng)一處理,同時加法和減法也可以統(tǒng)一處理。

補碼系統(tǒng)中,正數(shù)的補碼就是其本身,負數(shù)的補碼是在其原碼的基礎上,符號位不變,其余各位取反,最后加1。

在補碼表示法中,Integer.MIN_VALUE的二進制表示是10000000000000000000000000000000,取反后的結(jié)果是01111111111111111111111111111111,再加一變成10000000000000000000000000000000,這正好是Integer.MIN_VALUE本身。

因此,Math.abs(Integer.MIN_VALUE)的結(jié)果仍然是Integer.MIN_VALUE,即-2147483648。

解決問題

如何避免這個問題呢?兩種方式:

  1. 擴展數(shù)值范圍,在調(diào)用Math.abs方法是,把hash轉(zhuǎn)為Long類型,這個時候就不會越界了;
  2. 判斷hash值是否是Integer.MIN_VALUE,如果是,直接返回0。

總結(jié)問題

是不是有朋友會想,JDK中居然有這么低級錯誤的API。不過,這次的錯誤和JDK中居然也有反模式接口常量的不一樣,這次是“抽象泄漏法則”的一種情況。

什么是抽象泄漏法則?

“抽象泄漏”是軟件開發(fā)時,本應隱藏實現(xiàn)細節(jié)的抽象化不可避免地暴露出底層細節(jié)與局限性。抽象泄露是棘手的問題,因為抽象化本來目的就是向用戶隱藏不必要公開的細節(jié)。

由于軟件開發(fā)與運行環(huán)境越來越復雜,開發(fā)者必須依賴于各種抽象。使得開發(fā)者專注于高層次的領域相關的知識與技能,以提高工作效率。

但是,抽象泄漏法則指出“可靠”軟件的開發(fā)者必須了解抽象之下的底層細節(jié)。否則一旦出了任何問題,根本不會知道是怎么回事,也不知道如何除錯或回復。

程序設計工具抽象掉某些東西,但和其他所有抽象機制一樣都有漏洞,而唯一能適當處理漏洞的方法,就是弄懂該抽象原理以及所隱藏的東西。

所以抽象機制雖然節(jié)省了工作的時間,不過學習的時間是省不掉的。

比如本次的問題,Math.abs函數(shù)本身是一個簡單的抽象,用于計算一個數(shù)的絕對值。然而,由于 Integer.MIN_VALUE和反碼的特殊性質(zhì),Math.abs(Integer.MIN_VALUE)仍然返回負數(shù),這暴露了底層整數(shù)表示的細節(jié)。

這種抽象的泄漏使得我們在使用Math.abs(hash) % list.size()計算索引值時遇到了意料之外的問題。為了了解其中的原因,我們得需要知道數(shù)值在計算機中的表示形式。

所以,工具雖然好用,碰到問題也得撓頭。

少年,做好成為高級程序員的準備了嗎?


責任編輯:武曉燕 來源: 看山的小屋
相關推薦

2022-04-11 08:20:36

編程輔助工具GitHubCopilot

2023-12-12 08:41:01

2021-10-14 06:52:47

算法校驗碼結(jié)構(gòu)

2024-09-18 07:00:00

消息隊列中間件消息隊列

2022-09-29 15:32:58

云計算計算模式

2024-04-07 00:00:00

ESlint命令變量

2024-05-28 09:12:10

2022-03-10 08:25:27

JavaScrip變量作用域

2019-12-12 09:23:29

Hello World操作系統(tǒng)函數(shù)庫

2023-12-20 08:23:53

NIO組件非阻塞

2024-04-30 09:02:48

2023-04-26 10:21:04

2024-12-04 08:40:19

2014-05-30 10:23:15

樂跑手環(huán)智能手環(huán)運動手環(huán)

2021-10-28 16:19:37

物聯(lián)網(wǎng)人工智能IoT

2024-06-03 14:27:08

ThisAPIThat

2024-10-15 11:37:06

2024-06-20 08:06:30

2020-10-08 18:58:46

條件變量開發(fā)線程

2021-07-19 10:15:53

Java絕對值代碼
點贊
收藏

51CTO技術棧公眾號