以為是集合 sum 精度有問題,實際是bcadd的用法不正確。
這裡有一個計算
$data = [
[
"id" => 9,
"user_id" => 2,
"value" => 0.000013
],
[
"id" => 19,
"user_id" => 2,
"value" => 0.000009
]
];
$sumValue = collect($data)->sum('value');
\Log::info('$sumValue:' . $sumValue);
// 結果:$sumValue:2.2E-5 是科學記數法
\Log::info('bcadd:' . bcadd($sumValue, 0, 8));
// 結果: bcadd:0.00000000
\Log::info('sprintf:' . sprintf('%.8f', $sumValue));
// 結果:sprintf:0.00002200
bcadd 數字、字串、科學記數法型別的計算結果
1、數值
1) 4位小數,且前4位為0的
\Log::info('bcadd:' . bcadd(0.00002200, 0, 8));
// 結果:bcadd:0.00000000
2) 5位小數,且前4位有大於0的
\Log::info('bcadd:' . bcadd(0.00012200, 0, 8));
// 結果:bcadd:0.00012200
2、字串
\Log::info('bcadd:' . bcadd('0.00002200', 0, 8));
// 等同於 \Log::info('bcadd:' . bcadd((string)0.00012200, 0, 8));
// 結果:bcadd:0.00002200
3、科學記數法
1) 5位小數,且前4位有大於0的
\Log::info('bcadd:' . bcadd(2.2E-4, 0, 8));
// 結果:bcadd:0.00022000
2) 5位小數,且第4位等於0
\Log::info('bcadd:' . bcadd(2.2E-5, 0, 8));
// 結果:bcadd:0.00000000
3) 5為小數,第4位大於0
\Log::info('bcadd:' . bcadd(12.2E-5, 0, 8));
// 結果:bcadd:0.00012200
結論是超過4位小數,且前4位都為0時,如不轉為字串進行bcadd計算,那麼精度會有問題,結果會按0來計算;高精度計算,建議先轉為字串再進行計算。
根據需要,提前轉為精度+1的字串型別參與計算,如需保留6位,就取7位出來
$value = 0.000011;
$value = sprintf('%.7f', $value);
儲存資料時,可轉再轉為6位
$model->value = bcadd($value, 0, 6);
$model->save();
注:laravel 從mysql讀出的decimal型別的資料會轉換為字串型別,所以直接從資料庫查詢結果中取到的此型別欄位可以直接參與bc函式的計算。
預設使用mysqli 或者 pdo-mysql從資料庫中讀出來的資料都會轉換為字串型別,通過設定引數可以把int/float/tinyint等會轉為對應資料型別。laravel預設設定了這個轉換引數,如下圖:
參考:分享:Laravel 的 DB 查詢是如何實現欄位型別自動轉的?
詳細解釋:
部落格: Laravel Database——資料庫服務的啟動與連線
資料庫驅動參考:
https://www.jianshu.com/p/7a9c0bb8fe22
https://blog.csdn.net/weixin_34406061/arti...
本作品採用《CC 協議》,轉載必須註明作者和本文連結