【发布时间】:2011-01-12 10:04:10
【问题描述】:
我有这个 PHP 代码:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
我想知道的是,如何检查 $entityElementCount 是整数 (2, 6, ...) 还是部分 (2.33, 6.2, ...)。 p>
谢谢!
【问题讨论】:
标签: php integer double numbers
我有这个 PHP 代码:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
我想知道的是,如何检查 $entityElementCount 是整数 (2, 6, ...) 还是部分 (2.33, 6.2, ...)。 p>
谢谢!
【问题讨论】:
标签: php integer double numbers
if (floor($number) == $number)
【讨论】:
我知道这是旧的,但我想我会分享我刚刚发现的东西:
使用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 返回一个浮点数。
fmod返回一个浮点数,怎么会?返回一个浮点数是函数的目的(fmod = "float modules")。另外,我测试了你的理论,你是对的,它需要是`!== 0.0`。我会更新答案。
===0.0,这是由于处理过程中的一些估计。实际上,PHP 并不是为货币而设计的,这实际上会有所作为。请记住,准确度可能会根据 php.ini 中的precision 而发生变化
$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,在此示例中表示“不是整数”
我会像这样使用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)"
【讨论】:
基本的方式,正如茶茶所说的那样
if (floor($number) == $number)
但是,浮点类型不能准确存储数字,这意味着 1 可能存储为 0.999999997。这当然意味着上述检查将失败,因为它将向下舍入为 0,即使出于您的目的它足够接近到 1 以被视为整数。因此尝试这样的事情:
if (abs($number - round($number)) < 0.0001)
【讨论】:
如果您知道它将是数字(这意味着它永远不会将整数转换为字符串,例如 "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) 就足够了
is_int 调用的结果存储在一个变量中(我可能会以一种相当麻烦的方式添加)。此外,这会检查 var 是否为 int,而不是检查包含的值是否为整数。
我测试了所有提出的解决方案,其中提到了许多有问题的值,它们至少在一个测试用例中都失败了。开始检查$value 是否是一个数字,使用is_numeric($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不是一个整数。
round($value, 3)。使用round($value, 9) 产生float(0.999999997) is a whole number? no。
php.ini 中的precision 设置的约束。如果您将其设置为 8 或更少,则 float(0.999999997) 是一个整数。但是,如果您将其设置为 20 ,则为 float(0.999999997) => 0.99999999699999997382。默认值为 14 我认为这样仍然会产生差异。您的算法非常适用于统计数据,这是它的目的,但不是货币或输入验证。
if(floor($number) == $number)
不是一个稳定的算法。当数值为 1.0 时,数值可以是 0.9999999。如果你在它上面应用 floor() 它将是 0 不等于 0.9999999。
你必须猜测一个精度半径,例如 3 位数
if(round($number,3) == round($number))
【讨论】:
$num = 2.0000000000001;
if( $num == floor( $num ) ){
echo('whole');
}else{
echo('fraction');
}
前:
2.0000000000001 |分数
2.1 |分数
2.00 |整体
2 |整体
【讨论】:
(string)floor($pecahformat[3])!=(string)$pecahformat[3]
【讨论】:
$pecahformat=123.5 和$pecahformat="123.5" 上都失败,它认为123.5 是一个整数。
floor($entityElementCount) == $entityElementCount
如果这是一个整数,这将是正确的
【讨论】:
$entityElementCount="123foobar"; 上失败(它认为 123foobar 是一个整数。)
这并不是试图回答这个问题。他们已经有很多答案了。如果您像问题所暗示的那样进行统计,我怀疑@antonio-vinicius-menezes-medei 答案最适合您。但是我需要这个答案来验证输入。我发现这个检查更可靠地验证输入字符串是一个整数:
is_numeric($number) && preg_match('/^[0-9]+$/', $number)
“is_numeric”只是纠正 preg_match 中“true”转换为“1”的情况。
所以玩@antonio-vinicius-menezes-medei 的答案。我写了一个脚本来测试这个。注意ini_set('precision', 20)。 preg_match 会将参数转换为字符串。如果您的精度设置为低于浮点值的长度,它们将简单地以给定的精度四舍五入。与@antonio-vinicius-menezes-medei 回答类似,此精度设置将强制使用类似的估计长度。
ini_set('precision', 20);
$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);
foreach ($test_cases as $number)
{
echo '<strong>';
var_dump($number);
echo '</strong>';
echo boolFormater(is_numeric($number) && preg_match('/^[0-9]+$/', $number));
echo '<br>';
}
function boolFormater($value)
{
if ($value)
{
return 'Yes';
}
return 'No';
}
产生这个输出:
float(0.28999999999999998002) 否
int(2) 是
int(6) 是
float(2.3300000000000000711) 否
float(6.2000000000000001776) 否
string(5) "10.00" 否
float (1.3999999999999999112) 否
int(10) 是
string(2) "10" 是
float(10.5 ) 否
string(5) "0x539" 否
bool(true) 否
bool(false) 否
int(83) 是
float(9.4000000000000003553) 否
string(3) "十" 否
string(3) "100" 是
int(1) 是
float(0.99999999699999997382) 否
int(0) 是
float(0.00010000000000000000479) 否
float(1) 是
float(0.99999990000000005264) 否
float(2.0000000000000004441) 否
【讨论】:
@Tyler Carter 解决方案的改进版本,它比原来更好地处理边缘情况:
function is_whole_number($number){
return (is_float(($f=filter_var($number,FILTER_VALIDATE_FLOAT))) && floor($f)===$f);
}
(Tyler 的代码无法识别字符串“123foobar”不是整数。这个改进的版本不会犯这个错误。感谢 cmets 中的 @Shafizadeh 发现错误。这也是 php7 strict_types=1 -兼容)
【讨论】:
似乎一种简单的方法是使用模数 (%) 来确定一个值是否为整数。
x = y % 1
如果 y 不是整数,则结果不是零 (0)。那么测试将是:
if (y % 1 == 0) {
// this is a whole number
} else {
// this is not a whole number
}
var isWhole = (y % 1 == 0? true: false); // to get a boolean return.
当然,这会将负数视为一个整数,然后只需将 ABS() 包裹在 y 周围以始终测试正数。
【讨论】:
(x * 5.0) % 5.0) 但前提是 x 中的小数至少是 0.1,因为 php 会进行四舍五入。
我总是使用类型转换来检查变量是否包含整数,当您不知道值的来源或类型时很方便。
if ((string) $var === (string) (int) $var) {
echo 'whole number';
} else {
echo 'whatever it is, it\'s something else';
}
在你的特殊情况下,我会使用is_int()
if (is_int($var) {
echo 'integer';
}
【讨论】:
仅适用于正整数的简单解决方案。这可能并不适用于所有情况。
$string = '0x539';
$ceil = ceil($string);
if($ceil < 1){
$ceil = FALSE; // or whatever you want i.e 0 or 1
}
echo $ceil; // 1337
如果需要,您可以使用 floor() 代替 ceil()。
【讨论】:
function isInteger($value)
{
// '1' + 0 == int, '1.2' + 0 == float, '1e2' == float
return is_numeric($value) && is_int($value + 0);
}
function isWholeNumber($value)
{
return is_numeric($value)
&& (is_int($value + 0)
|| (intval($value + 0) === intval(ceil($value + 0))));
}
如果要同时检查整数和小数,可以执行以下操作:
if (isInteger($foo))
{
// integer as int or string
}
if (isWholeNumber($foo))
{
// integer as int or string, or float/double with zero decimal part
}
else if (is_numeric($foo))
{
// decimal number - still numeric, but not int
}
这将正确检查您的数字,而无需对其进行四舍五入、将其转换为 int(在十进制数字的情况下将丢失小数部分)或进行任何数学运算。但是,如果您想将 1.00 视为一个整数,那就另当别论了。
【讨论】:
我知道这是一篇超级旧的帖子,但这是一个简单的函数,它将返回一个有效的整数并将其转换为一个 int。如果失败则返回 false。
function isWholeNumber($v)
{
if ($v !='' && is_numeric($v) && strpos($v, '.') === false) {
return (int)$v;
}
return false;
}
用法:
$a = 43;
$b = 4.3;
$c = 'four_three';
isWholeNumber($a) // 43
isWholeNumber($b) // false
isWholeNumber($c) // false
【讨论】:
只是为了与本地化字符串/数字分享我的解决方案,这个组合对我来说就像一个魅力。
public static function isWholeNumber ($input, $decimalDelimiter = ',')
{
if (is_string($input)){
$input = str_replace($decimalDelimiter, '.', $input);
$input = floatval($input);
}
if (fmod($input,1) !== 0.0) {
return false;
}
return true;
}
【讨论】:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
Method 1-
By using ctype_digit() function.
if ( ctype_digit($entityElementCount )) {
echo "Whole Number\n";
} else {
echo "Not a whole Number\n";
}
Method 2-
By using is_float() function.
if (is_float($entityElementCount )) {
echo "Not a Whole Number\n";
} else {
echo "Whole Number\n";
}
Method 3-
By using is_int() function.
if (is_int($entityElementCount )) {
echo "Whole Number\n";
} else {
echo "Not a whole Number\n";
}
Method 5-
By using fmod() function.
It needs 2 parameters one dividend and other is divisor
Here $dividend=$entityElementCount and divisor=1
if (fmod($dividend,$divisor) !== 0.0) {
echo 'Not a whole number!';
} else {
echo 'A whole number!';
}
there are some more function like intval(), floor(),... can be used to check it`enter code here`
【讨论】:
我想出的另一种 hacky 方式是 ceil($value) === floor($value)。如果一个数字是一个整数,这应该总是正确的,即使将 10 与 10.000 进行比较,甚至可以使用字符串中的数字,例如ceil("10.0") === floor(10)。
【讨论】: