快轉到主要內容
Background Image

PHP Intval 的 8、7 運算 8、7 問題

乾太
作者
乾太
一起寫程式的好朋友。
目錄
PHP 浮點數運算精度問題的深入分析。為什麼簡單的 0.1 + 0.7 經過 intval 處理後會出現意外的結果?

問題描述
#

常見的 PHP 浮點數問題

在 PHP 中,小數運算經常會遇到精度問題。例如:有 $a = 0.1 與 $b = 0.7 這兩個變數,相加乘以 10 後應該得到 8,但 intval 的結果卻是 7。

intval 函數介紹
#

intval 是獲得變數整數值的方法,先參考 php.net 官方文件

intval
#

<?php
function intval ($var, $base = null) {}
Get the integer value of a variable

intval

Get the integer value of a variable

<?php
function intval($var, $base = 10) { }
@param mixed $var — The scalar value being converted to an integer

@param int $base — [optional]

The base for the conversion

@return int
The integer value of var on success, or 0 on failure. Empty arrays and objects return 0, non-empty arrays and objects return 1.

The maximum value depends on the system. 32 bit systems have a maximum signed integer range of -2147483648 to 2147483647. So for example on such a system, intval('1000000000000') will return 2147483647. The maximum signed integer value for 64 bit systems is 9223372036854775807.

Strings will most likely return 0 although this depends on the leftmost characters of the string. The common rules of integer casting apply.

@link https://php.net/manual/en/function.intval.php

Get the integer value of a variable

intval( mixed $var [, int $base = 10 ]): integer

那我們就不囉唆,實際來測試一下 intval 如果真的把 $a = 0.1$b = 0.7 相加後乘以 10 會得出什麼結果?

$a = 0.1;
$b = 0.7;

$c = intval(($a + $b) * 10);
echo $c; // 7

這問題還蠻神奇的,那如果以此類推的話,乘以 20 會得到 14,乘以 100 會得到 70 囉?二話不說馬上來測試。

$a = 0.1;
$b = 0.7;

$c = intval(($a + $b) * 20);
echo $c; // 15

$c = intval(($a + $b) * 100);
echo $c; // 80

這樣的結果還蠻訝異的,它居然會在乘以 20 的時候 $a + $b 就變成 7.5,然後乘以 100 的時候則變成 8,這個 $a + $b 的內容是什麼,我們有必要來檢查一下。

$a = 0.1;
$b = 0.7;

$c = $a + $b;
echo $c; // 0.8

$c = $c * 10;
echo $c; // 8

到這邊都還蠻正常的,我們已經可以確信 $c 是 8,所以如果我直接把 $c 丟進去 intval 的話,整數 8 進去應該會獲得整數 8 囉?

$a = 0.1;
$b = 0.7;

$c = $a + $b;
$c = $c * 10;

echo intval($c); // 7

1.png

反正無論如何,我只要確信我給 intval 的是 8,無論這個 8 是整數是浮點數是字串,只要它看起來像 8,只要你看得懂我給你的是 8 的話,你就會跟我說 8 對不對?

intval: 對。

$a = 0.1;
$b = 0.7;

$c = $a + $b;
$c = $c * 10;

echo intval(strval($c)); // 8

我把 $c 給先轉成字串,再把它 intval 去處理,最後終於真真切切地得到 8 了,但這不像是一個好的做法,因此在此推廣 …

珍惜生命,請學習型別宣告。
#

(double) $a = 0.1;
(double) $b = 0.7;
(int) $c = ($a + $b) * 10;

echo $c; // 8