我有以下这段PHP代码:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
我的问题是如何检查$entityElementCount是否为整数(2、6、...)或小数(2.33、6.2、...)。
谢谢!
if (floor($number) == $number)
2.000000000000000444089209850062616169452667236328125
(至少在64位php上),Tyler的代码运行良好。- 尝试 $number = (-(4.42-5))/0.29; var_dump(number_format($number,100));
以查看所有数字的 $number(大多数函数,如 echo/var_dump 等都不显示所有数字,但是 number_format,使用正确的参数,可以显示所有数字)。 - hanshenrik虽然这已经过时了,但我想分享一些我刚发现的东西:
使用fmod函数并检查是否为0。
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
if (fmod($entityElementCount,1) !== 0.0) {
echo 'Not a whole number!';
} else {
echo 'A whole number!';
}
fmod与%不同,因为如果你有一个分数,%在我这里似乎不起作用(它返回0......例如,echo 9.4 % 1;
将输出0
)。使用fmod,您将获得小数部分。例如:
echo fmod(9.4, 1);
将输出0.4
===
或 !==
),正如大多数安全顾问建议的那样,fmod
函数会返回一个浮点数,因此您需要执行类似于 fmod($a,1)=== 0.0
的操作来确保它是整数。我也不完全确定这是否准确。很遗憾 fmod
返回一个浮点数。 - danielson317fmod
返回浮点数是不幸的,为什么呢?返回浮点数是函数的目的(fmod = "float modulus")。另外,我测试了一下你的理论,你是对的,需要写成 !== 0.0
。我会更新答案的。 - Joseph===0.0
。实际上,PHP并不是为货币设计的,这实际上并没有什么区别。请记住,精度可能会根据php.ini中的“precision”而改变。 - danielson317$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
if (ctype_digit($entityElementCount) ){
// (ctype_digit((string)$entityElementCount)) // as advised.
print "whole number\n";
}else{
print "not whole number\n";
}
ctype_digit('10.00')
返回FALSE,表示“不是整数” - Philipp我会像这样使用intval函数:
if($number === intval($number)) {
}
测试:
var_dump(10 === intval(10)); // prints "bool(true)"
var_dump("10" === intval("10")); // prints "bool(false)"
var_dump(10.5 === intval(10.5)); // prints "bool(false)"
var_dump("0x539" === intval("0x539")); // prints "bool(false)"
1)
if(floor($number) == $number) { // Currently most upvoted solution:
测试:
$number = true;
var_dump(floor($number) == $number); // prints "bool(true)" which is incorrect.
2)
if (is_numeric($number) && floor($number) == $number) {
特殊情况:
$number = "0x539";
var_dump(is_numeric($number) && floor($number) == $number); // prints "bool(true)" which depend on context may or may not be what you want
3)
if (ctype_digit($number)) {
测试:
var_dump(ctype_digit("0x539")); // prints "bool(false)"
var_dump(ctype_digit(10)); // prints "bool(false)"
var_dump(ctype_digit(0x53)); // prints "bool(false)"
如Chacha所说,最基本的方法是
if (floor($number) == $number)
然而,浮点数类型无法精确地存储数字,这意味着1可能会被存储为0.999999997。这当然会导致上面的检查失败,因为它将被舍入为0,即使对于您的目的而言,它足以被视为整数。因此,尝试使用以下代码:
if (abs($number - round($number)) < 0.0001)
我测试了所有提出的解决方案,使用了许多有问题的值,它们在至少一个测试用例中都失败了。使用is_numeric($value)
检查$value
是否为数字可以减少许多解决方案的失败次数,但并不能将任何解决方案变成终极解决方案:
$test_cases = array(0.29, 2, 6, 2.33, 6.2, '10.00', 1.4, 10, "10", 10.5, "0x539", true,
false, 0x53, 9.4, "ten", "100", 1, 0.999999997, 0, 0.0001, 1.0, 0.9999999,
(-(4.42-5))/0.29);
function is_whole_number($value) {
// Doing this prevents failing for values like true or "ten"
if (!is_numeric($value)) {
return false;
}
// @ghostdog74's solution fails for "10.00"
// return (ctype_digit((string) $value));
// Both @Maurice's solutions fails for "10.00"
// return ((string) $value === (string) (int) $value);
// return is_int($value);
// @j.hull's solution always returns true for numeric values
// return (abs($value) % 1 == 0 ? true : false);
// @ MartyIX's solution fails for "10.00"
// return ($value === intval($value));
// This one fails for (-(4.42-5))/0.29
// return (floor($value) == $value);
// This one fails for 2
// return ctype_digit($value);
// I didn't understand Josh Crozier's answer
// @joseph4tw's solution fails for (-(4.42-5))/0.29
// return !(fmod($value, 1) != 0);
// If you are unsure about the double negation, doing this way produces the same
// results:
// return (fmod($value, 1) == 0);
// Doing this way, it always returns false
// return (fmod($value, 1) === 0);
// @Anthony's solution fails for "10.00"
// return (is_numeric($value) && is_int($value));
// @Aistina's solution fails for 0.999999997
// return (abs($value - round($value)) < 0.0001);
// @Notinlist's solution fails for 0.999999997
// return (round($value, 3) == round($value));
}
foreach ($test_cases as $test_case) {
var_dump($test_case);
echo ' is a whole number? ';
echo is_whole_number($test_case) ? 'yes' : 'no';
echo "\n";
}
我认为像 @Aistina 和 @Notinlist 提出的解决方案是最好的,因为它们使用误差阈值来确定一个值是否为整数。需要注意的是,对于表达式 (-(4.42-5))/0.29
,它们都能够正常工作,而其他所有解决方案在该测试用例中均失败。
我决定使用 @Notinlist 的解决方案,因为它更易读:
function is_whole_number($value) {
return (is_numeric($value) && (round($value, 3) == round($value)));
}
我需要测试数值是否为整数、货币或百分比,我认为精度的2位数字就足够了,所以@Notinlist的解决方案符合我的需求。
运行此测试:
$test_cases = array(0.29, 2, 6, 2.33, 6.2, '10.00', 1.4, 10, "10", 10.5, "0x539", true,
false, 0x53, 9.4, "ten", "100", 1, 0.999999997, 0, 0.0001, 1.0, 0.9999999,
(-(4.42-5))/0.29);
function is_whole_number($value) {
return (is_numeric($value) && (round($value, 3) == round($value)));
}
foreach ($test_cases as $test_case) {
var_dump($test_case);
echo ' is a whole number? ';
echo is_whole_number($test_case) ? 'yes' : 'no';
echo "\n";
}
float(0.29)
is a whole number? no
int(2)
is a whole number? yes
int(6)
is a whole number? yes
float(2.33)
is a whole number? no
float(6.2)
is a whole number? no
string(5) "10.00"
is a whole number? yes
float(1.4)
is a whole number? no
int(10)
is a whole number? yes
string(2) "10"
is a whole number? yes
float(10.5)
is a whole number? no
string(5) "0x539"
is a whole number? yes
bool(true)
is a whole number? no
bool(false)
is a whole number? no
int(83)
is a whole number? yes
float(9.4)
is a whole number? no
string(3) "ten"
is a whole number? no
string(3) "100"
is a whole number? yes
int(1)
is a whole number? yes
float(0.999999997)
is a whole number? yes
int(0)
is a whole number? yes
float(0.0001)
is a whole number? yes
float(1)
is a whole number? yes
float(0.9999999)
is a whole number? yes
float(2)
is a whole number? yes
0.999999997
不是个整数。 - danielson317round($value, 3)
即可。使用 round($value, 9)
会产生 float(0.999999997) 是整数吗?不是
。 - Antônio Medeirosphp.ini
中的precision
设置的影响。如果您将其设置为8或更少,则float(0.999999997)
是一个整数。但是,如果您将其设置为20,则float(0.999999997) => 0.99999999699999997382
。默认值是14,所以仍会产生差异。您的算法在统计方面非常有效,这也是它在此处的目的,但不适用于货币或输入验证。 - danielson317如果你知道它将是数字(意味着它永远不会是一个整数转换为字符串,比如"ten"
或"100"
),你可以直接使用is_int()
:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
$entityWholeNumber = is_int($entityElementCount);
echo ($entityWholeNumber) ? "Whole Number!" : "Not a whole number!";
$entityWholeNumber = is_int($entityElementCount)
就足够了。 - Iain Fraseris_int
调用的结果存储在一个变量中。此外,这检查的是变量是否为整数,而不是其所包含的值是否为整数。 - Aistinaif(floor($number) == $number)
这不是一个稳定的算法。当数值在数学上为1.0时,其数值可以为0.9999999。如果对其应用floor()函数,则结果为0,而不等于0.9999999。
你需要猜测一个精度半径,例如3位小数。
if(round($number,3) == round($number))
我想到的另一种hacky方法是 ceil($value) === floor($value)
。如果一个数字是整数,这应该总是正确的,即使比较10和10.000,甚至可以用于将数字强制转换为字符串进行比较,例如ceil("10.0") === floor(10)
。
$num = 2.0000000000001;
if( $num == floor( $num ) ){
echo('whole');
}else{
echo('fraction');
}
2.0000000000001 | 分数
2.1 | 分数
2.00 | 整数
2 | 整数
ctype_digit($num)
。 - Beyondo