踩坑之json encode精度丟失問題

2021-10-05 03:05:28 字數 2140 閱讀 4462

【推薦閱讀】微服務還能火多久?>>>

最近在工作中,後台出現了這樣的錯誤,傳遞的手續費是29塊錢,但是傳遞到了第三方介面就報錯了,檢視日誌顯示該手續費變成了28.999999999999996,日誌如下:

明明是29怎麼就變了?通過斷點檢測,原來是json_encode()轉換的問題

$param=

var_dump(json_encode($param));//

$request['param']['feeamount']=(string)$request['param']['feeamount'];

注意:使用這種方法千萬要注意,對接介面是否有變數型別要求

number_format(number,decimals,decimalpoint,separator)

引數: 案例:

$request['param']['feeamount']=(int)number_format($request['param']['feeamount'],0);

注意:number_format返回的是字串string,要注意介面是否有規範要求,如果有,則須強行轉換為int或介面規範的型別

疑問1:這時候應該有人在想能不能直接強制轉換為int呢?注意,float強制轉換成int有坑!

答:int型別是向下取整的,比如:12910.9 會被轉換為 12910

疑問2:這時就會有人問我,浮點數顯示的是8,為什麼轉換成整數會變成7?

答:floor((0.1+0.7)*10),其結果是7而不是8,是因為該結果內部表示的是7.9999.....所以不要相信浮點數結果精確,也不要比較兩個浮點數是否相等

json_encode() 轉換浮點小數溢位現象只出現在php 7.1+版本,是因為php原始碼對於json_encode()轉換使用到了serialize_precision配置項,如下圖

static inline void php_json_encode_double(smart_str *buf, double d, int options) /* 

}

關於php函式serialize_precision (integer)的一些概念了解:適用範圍:php_ini_all;

預設值:100

serialize_precision指令的數量決定了雙打和彩車被序列化後的浮點數字儲存。設定到乙個合適的值,確保精度的數字時,可能丟失以後反序列化。所以我們要使得json_encode()轉換浮點數沒有小數溢位,建議使用預設值 serialize_precision = -1 即可 。

json_encode有個選項json_preserve_zero_fraction,表示如果是個整數, 是否保留小數點和尾數0,舉例如下:

<?php 

echo json_encode(223.0);// 223

echo json_encode(223.0, json_preserve_zero_fraction);// 223.0

四捨五入取整 round(param)

向上取整 ceil(param)

向下取整 floor(param)

格式:

string bcsub ( string $left_operand , string $right_operand [, int $scale = int ] )

說明:

2個任意精度數字的減法

引數:

left_operand:字串型別的左運算元.

right_operand:字串型別的右運算元.

scale:此可選引數用於設定結果中小數點後的小數字數。也可通過使用 bcscale() 來設定全域性預設的小數字數,用於所有函式。

返回值:

返回減法之後結果為字串型別.

**案例:

<?php

$a  =  '1.234' ;

$b  =  '5' ;

echo  bcsub ( $a ,  $b );      // -3

echo  bcsub ( $a ,  $b ,  4 );   // -3.7660

javascript之踩坑記錄

console.log true console.log false 這個坑在於js裡的 和 的區別。1 對於string,number等基礎型別,和 是有區別的 1 不同型別間比較,之比較 轉化成同一型別後的值 看 值 是否相等,如果型別不同,其結果就是不等 2 同型別比較,直接進行 值 比較,兩...

SpringCloud之試探踩坑

一直rpc呼叫都是使用dubbo介面,近來微服務比較火?開始使用springcloud的介面,使用 feignclient的呼叫方式。註冊中心eureka,用於服務註冊和發現。介面呼叫的實質就是restful介面,通過spring內部封裝的httpclient方式請求呼叫。資料傳遞使用json格式,...

套裁問題之踩坑記

前些天乙個老哥要我做個板材套裁的東東,我看了下覺得很簡單,結果一腳就踩了個大坑。套裁就是在板材加工之前如何裁板,就是從指定規格的原材中如何最小消耗的裁出需要數量的各種板材。我一想,這不就是個揹包問題嗎,結果做起來才發現想得太簡單了,在第一步就暈了 如何找出所有可用的揹包 即如何放置待切割板材 套裁問...