How I can create my own pow function using PHP? - php

I want to create a function in which I put two values (value and its power - Example function: multiply(3, 3) result 27). I have tried so far but failed, I have searched using Google but I have been unable to find any result because I don't know the name of this function.
What I want exactly:
3,3 => 3 x 3 x 3 = 27
4,4 => 4 x 4 x 4 x 4 = 256
What I tried:
function multiply($value,$power){
for($x = 1; $x <= $value; $x++ ){
return $c = $value * $power;
}
}
echo multiply(3,3);

The answer has already been accepted, but I had to come here and say that all answers here use a bad algorithm. There are better ones. Including very simple ones, like exponentiation by squaring that reduces the complexity from O(power) to O(log(power)).
The idea is to square the base while dividing the exponent by 2. For example
3^8 = 9^4 = 81^2 = 6561
There is a special case when the exponent is odd. In this case, you must store a separate variable to represent this factor:
2^10 = 4^5 = 16^2 * 4 = 256 * 4 = 1024
PHP isn't one of my strong skills, but the final algorithm is as simple as:
function multiply($value, $power){
$free = 1;
while ($power > 1) {
if ($power % 2 == 1)
$free *= $value;
$value *= $value;
$power >>= 1; //integer divison by 2
}
return $value*$free;
}
echo multiply(3, 3) . "\n";
echo multiply(2, 10) . "\n";
echo multiply(3, 8) . "\n";

Oopsika, couldn't have asked a more obvious question. Use the built-in function named pow (as in a lot of languages)
echo pow(3, 3);
Edit
Let's create our own function.
function raiseToPower($base,$exponent)
{
// multiply the base to itself exponent number of times
$result=1;
for($i=1;$i<=$exponent;$i++)
{
$result = $result * $base;
}
return $result;
}

function exponent($value,$power)
{
$c=1;
for($x = 1; $x <= $power; $x++ )
{
$c = $value * $c;
}
return $c;
}

If you have PHP >= 5.6 you can use the ** operator
$a ** $b Exponentiation Result of raising $a to the $b'th power.
echo 2 ** 3;
If you have PHP < 5.6 you can use pow:
number pow ( number $base , number $exp )
echo pow(2, 3);
Your own function is:
function multiply($value, $power) {
$result = 1;
for($x = 1; $x <= $power; $x++){
$result *= $value;
}
return $result;
}
echo multiply(3,3);
Read more at:
http://php.net/manual/en/language.operators.arithmetic.php
http://php.net/manual/en/function.pow.php

Just try to run this code I hope your problem will be solved.
If you defining any function then you have to call it return value.
<?php
function multiply($value,$exp)
{ $temp=1;
if($exp==0)
return $temp;
else
{
for($i=1;$i<=$exp;$i++)
$temp=$temp*$value;
return $temp;
}
}
echo multiply(5,6);
?>

echo "Enter number (will be mutiplied):".PHP_EOL;
$value = (int) readline("> ");
echo "Enter number for multiplier:".PHP_EOL;
$multiplier = (int) readline("> ");
function power(int $i, int $n):int {
$result =1;
for ($int = 1; $int < $n; $int++){
$result *= $i;
}
return $result;
}
echo power($value,$multiplier);

Related

PHP check if is integer

I have the following calculation:
$this->count = float(44.28)
$multiple = float(0.36)
$calc = $this->count / $multiple;
$calc = 44.28 / 0.36 = 123
Now I want to check if my variable $calc is integer (has decimals) or not.
I tried doing if(is_int()) {} but that doesn't work because $calc = (float)123.
Also tried this-
if($calc == round($calc))
{
die('is integer');
}
else
{
die('is float);
}
but that also doesn't work because it returns in every case 'is float'. In the case above that should'n be true because 123 is the same as 123 after rounding.
Try-
if ((string)(int) $calc === (string)$calc) {
//it is an integer
}else{
//it is a float
}
Demo
As CodeBird pointed out in a comment to the question, floating points can exhibit unexpected behaviour due to precision "errors".
e.g.
<?php
$x = 1.4-0.5;
$z = 0.9;
echo $x, ' ', $z, ' ', $x==$z ? 'yes':'no';
prints on my machine (win8, x64 but 32bit build of php)
0.9 0.9 no
took a while to find a (hopefully correct) example that is a) relevant to this question and b) obvious (I think x / y * y is obvious enough).
again this was tested on a 32bit build on a 64bit windows 8
<?php
$y = 0.01; // some mambojambo here...
for($i=1; $i<31; $i++) { // ... because ...
$y += 0.01; // ... just writing ...
} // ... $y = 0.31000 didn't work
$x = 5.0 / $y;
$x *= $y;
echo 'x=', $x, "\r\n";
var_dump((int)$x==$x);
and the output is
x=5
bool(false)
Depending on what you're trying to achieve it might be necessary to check if the value is within a certain range of an integer (or it might be just a marginalia on the other side of the spectrum ;-) ), e.g.
function is_intval($x, $epsilon = 0.00001) {
$x = abs($x - round($x));
return $x < $epsilon;
};
and you might also take a look at some arbitrary precision library, e.g. the bcmath extension where you can set "the scale of precision".
You can do it using ((int) $var == $var)
$var = 9;
echo ((int) $var == $var) ? 'true' : 'false';
//Will print true;
$var = 9.6;
echo ((int) $var == $var) ? 'true' : 'false';
//Will print false;
Basically you check if the int value of $var equal to $var
round() will return a float. This is because you can set the number of decimals.
You could use a regex:
if(preg_match('~^[0-9]+$~', $calc))
PHP will convert $calc automatically into a string when passing it to preg_match().
You can use number_format() to convert number into correct format and then work like this
$count = (float)(44.28);
$multiple = (float)(0.36);
$calc = $count / $multiple;
//$calc = 44.28 / 0.36 = 123
$calc = number_format($calc, 2, '.', '');
if(($calc) == round($calc))
die("is integer");
else
die("is not integer");
Demo
Ok I guess I'am pretty late to the party but this is a alternative using fmod() which is a modulo operation. I simply store the fraction after the calculation of 2 variables and check if they are > 0 which would imply it is a float.
<?php
class booHoo{
public function __construct($numberUno, $numberDos) {
$this->numberUno= $numberUno;
$this->numberDos= $numberDos;
}
public function compare() {
$fraction = fmod($this->numberUno, $this->numberDos);
if($fraction > 0) {
echo 'is floating point';
} else {
echo 'is Integer';
}
}
}
$check= new booHoo(5, 0.26);
$check->compare();
Eval here
Edit: Reminder Fmod will use a division to compare numbers the whole documentation can be found here
if (empty($calc - (int)$calc))
{
return true; // is int
}else{
return false; // is no int
}
Try this:
//$calc = 123;
$calc = 123.110;
if(ceil($calc) == $calc)
{
die("is integer");
}
else
{
die("is float");
}
you may use the is_int() function at the place of round() function.
if(is_int($calc)) {
die('is integer');
} else {
die('is float);
}
I think it would help you
A more unorthodox way of checking if a float is also an integer:
// ctype returns bool from a string and that is why use strval
$result = ctype_digit(strval($float));

How can I optimize this 'lottery' function in PHP?

Earlier I wrote a code in Matlab for this sort of lottery function, just to test if it was possible. However, I actually needed it in PHP so I've just rewritten the code and it does seem to work, but as it involves a lot of looping I want to make sure I'm doing it as efficiently as possible.
What the code does:
You can call the function $lotto -> type($users,$difficulty) and it will return two numbers. Here's the explanation, $users is the number of users registered on the website, i.e the people who will potentially buy a ticket. $difficulty is a number between 1 and 10, where 5 is normal, 1 is easy and 10 is hard. Difficulty here means how hard it is to match all numbers on a lottery ticket.
So what are the numbers that the function returns? That would be $n and $r. $n is the amount of numbers there will be on the lottery ticket, and $r is the amount of numbers you can choose from the lottery ticket. For example, in the UK a national lottery ticket has 49 numbers if which you choose 6. I.e $n = 49 and $r = 6.
How does the function calculate these two numbers? In the UK national lottery there are 13,983,816 different possible ticket combinations. If I were to run $lotto -> type(13983816,1) it would return array(49,6). Basically it tried to make it so there are as many combinations of tickets as there are registered users.
tl;dr, here's the code:
<?php
class lotto {
public function type($users,$difficulty){
$current_r = $r = 2;
$current_n = 0;
$difficulty = ($difficulty + 5) / 10; // sliding scale from 1 - 10
$last_tickets_sold = 200; // tickets sold in last lotto
$last_users = 100; // how many users there were in the last lotto
$last_factor = $last_tickets_sold / $last_users; // tickets per user
$factor = $last_factor * $difficulty;
$users *= $factor;
while($r <= 10){
$u = 0;
$n = $r;
while($u < $users && $n < 50){
$u = $this -> nCr(++$n,$r);
}
if($r == 2){
$current_n = $n;
} elseif(abs($this -> nCr($n,$r) - $users) < abs($this -> nCr($current_n,$current_r) - $users)){
// this is a better match so update current n and r
$current_r = $r;
$current_n = $n;
}
$r++;
}
return array($current_n,$current_r);
}
private function nCr($n,$r){
return $this -> factorial($n) / (
$this -> factorial($r) * $this -> factorial($n - $r)
);
}
private function factorial($x){
$f = $x;
while(--$x){
$f *= $x;
}
return $f;
}
}
$lotto = new lotto;
print_r($lotto -> type(1000,5));
?>
I did a quick scan and spotted a few places that can be further optimized.
Combination
Your algorithm is a brute force one and can be further optimized
private function nCr($n,$r){
return $this -> factorial($n) / (
$this->factorial($r) * $this->factorial($n - $r)
);
}
to
function nCr($n,$r) {
$top = 1;
$sub = 1;
for($i = $r+1; $i <= $n; $i++)
$top *= $i;
$n -= $r;
for($i = 2; $i <= $n; $i++)
$sub *= $i;
return $top / $sub;
}
Too Much Combination Calculation
Calculate combination is expensive.
$u = 0;
$n = $r;
while($u < $users && $n < 50){
$u = $this -> nCr(++$n,$r);
}
to
$n = $r + 1;
$u = nCr($n, $r);
while ($u < $users && $n < 50) {
$n++;
$u *= $n;
$u /= ($n - $r);
}
An immediate observation is that you have the possibility of a divide by 0 error
$last_factor = $last_tickets_sold / $last_users;
Could be solved by putting a simple if statement around it
$last_factor = ($last_users == 0) ? 0 : $last_tickets_sold / $last_users;
Regardless detailed examination of your code, are you sure that your loops does not need continue or break?
The range of factorial() in your algo is [0,50], so why not just precompute this statically?
private static $factorial=array(1);
private static genFactorial($max) {
if( count( self::$factorial ) > $max ) return;
foreach ( range(count(self::$factorial), $max) as $n ) {
self::$factorial[$n] = $i*self::$factorial[$n-1];
}
}
Now add a self::genFactorial(50); to __construct() or to type() and replace references to $this -> factorial($n) by self::$factorial[$n].
This is just a quick code dump; not even compile checked so forgive any typos, etc. but what this does is to replace a function call (which includes a while loop) by an array element fetch.

PHP "Maximum execution time"

I'm trying to program my own Sine function implementation for fun but I keep getting :
Fatal error: Maximum execution time of 30 seconds exceeded
I have a small HTML form where you can enter the "x" value of Sin(x) your looking for and the number of "iterations" you want to calculate (precision of your value), the rest is PhP.
The maths are based of the "Series definition" of Sine on Wikipedia :
--> http://en.wikipedia.org/wiki/Sine#Series_definition
Here's my code :
<?php
function factorial($int) {
if($int<2)return 1;
for($f=2;$int-1>1;$f*=$int--);
return $f;
};
if(isset($_POST["x"]) && isset($_POST["iterations"])) {
$x = $_POST["x"];
$iterations = $_POST["iterations"];
}
else {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
if(isset($x) && is_numeric($x) && isset($iterations) && is_numeric($iterations)) {
$x = floatval($x);
$iterations = floatval($iterations);
for($i = 0; $i <= ($iterations-1); $i++) {
if($i%2 == 0) {
$operator = 1;
global $operator;
}
else {
$operator = -1;
global $operator;
}
}
for($k = 1; $k <= (($iterations-(1/2))*2); $k+2) {
$k = $k;
global $k;
}
function sinus($x, $iterations) {
if($x == 0 OR ($x%180) == 0) {
return 0;
}
else {
while($iterations != 0) {
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
$iterations = $iterations-1;
return $result;
}
}
}
$result = sinus($x, $iterations);
global $result;
}
else if(!isset($x) OR !isset($iterations)) {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
else if(isset($x) && !is_numeric($x)&& isset($iterations) && is_numeric($iterations)) {
$error = "Not a valid number.";
global $error;
}
?>
My mistake probably comes from an infinite loop at this line :
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
but I don't know how to solve the problem.
What I'm tring to do at this line is to calculate :
((pow($x, $k)) / (factorial($k)) + (((pow($x, $k))/(factorial($k)) * ($operator)
iterating :
+ (((pow($x, $k))/(factorial($k)) * $operator)
an "$iterations" amount of times with "$i"'s and "$k"'s values changing accordingly.
I'm really stuck here ! A bit of help would be needed. Thank you in advance !
Btw : The factorial function is not mine. I found it in a PhP.net comment and apparently it's the optimal factorial function.
Why are you computing the 'operator' and power 'k' out side the sinus function.
sin expansion looks like = x - x^2/2! + x^3/3! ....
something like this.
Also remember iteration is integer so apply intval on it and not floatval.
Also study in net how to use global. Anyway you do not need global because your 'operator' and power 'k' computation will be within sinus function.
Best of luck.
That factorial function is hardly optimal—for speed, though it is not bad. At least it does not recurse. It is simple and correct though. The major aspect of the timeout is that you are calling it a lot. One technique for improving its performance is to remember, in a local array, the values for factorial previously computed. Or just compute them all once.
There are many bits of your code which could endure improvement:
This statement:
while($iterations != 0)
What if $iterations is entered as 0.1? Or negative. That would cause an infinite loop. You can make the program more resistant to bad input with
while ($iterations > 0)
The formula for computing a sine uses the odd numbers: 1, 3, 5, 7; not every integer
There are easier ways to compute the alternating sign.
Excess complication of arithmetic expressions.
return $result is within the loop, terminating it early.
Here is a tested, working program which has adjustments for all these issues:
<?php
// precompute the factorial values
global $factorials;
$factorials = array();
foreach (range (0, 170) as $j)
if ($j < 2)
$factorials [$j] = 1;
else $factorials [$j] = $factorials [$j-1] * $j;
function sinus($x, $iterations)
{
global $factorials;
$sign = 1;
for ($j = 1, $result = 0; $j < $iterations * 2; $j += 2)
{
$result += pow($x, $j) / $factorials[$j] * $sign;
$sign = - $sign;
}
return $result;
}
// test program to prove functionality
$pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620;
$x_vals = array (0, $pi/4, $pi/2, $pi, $pi * 3/2, 2 * $pi);
foreach ($x_vals as $x)
{
$y = sinus ($x, 20);
echo "sinus($x) = $y\n";
}
?>
Output:
sinus(0) = 0
sinus(0.78539816339745) = 0.70710678118655
sinus(1.5707963267949) = 1
sinus(3.1415926535898) = 3.4586691443274E-16
sinus(4.7123889803847) = -1
sinus(6.2831853071796) = 8.9457384260403E-15
By the way, this executes very quickly: 32 milliseconds for this output.

Rounding up to next significant figure

I need to round up any integer between 1 and infinity in php to the next significant figure (though in practice I'm unlikely to need to round up infinity, so will be happy to settle on reasonable internal limits) eg:
$x <= 10 ? $x = 10
10 < $x <= 100 ? $x = 100
100 < $x <= 1000 ? $x = 1000
etc.
Round / ceil etc don't seem to do the job quite as planned. A pointer towards the correct algorhythm (or function?) would be much appreciated
i think this method will fix your problem:
function n($nr, $p = 10) {
if($nr <= $p) {
return $p;
}
return n($nr, $p*10);
}
heres the result:
echo n(1);
//output 10
echo n(232);
//output 1000
echo n(89289382);
//output 100000000
$x = pow(10,floor(log10($x)) + (floor(log10($x)) == log10($x) && $x!=1 ? 0:1) );
function my_ceil($in) {
if($in == 1) return $in;
if($in == pow(10, strlen($in)-1)) return $in;
return pow(10, strlen($in));
}
echo my_ceil(11); //100
echo my_ceil(10); //10
I think this is what you're looking for:
echo ceil($x / pow(10, strlen($x))) * pow(10, strlen($x));
Only works when $x is an integer, but you say in your question that that is indeed the case, so there's no issue (unless you try to later use it with numbers containing decimals).
This should do the trick:
<?php
function nextSignificantFeature($number){
$upper = pow(10, strlen($number));
return $number == $upper/10 ? $number : $upper;
}
?>
Actually there is the infinity number in PHP, so the implementation should deal with it as you wrote any number from 1 up to infinity Demo:
<?php
function n($number) {
if ($number < 1) {
throw new InvalidArgumentException('Number must be greater or equal 1.');
}
if ($number === INF) {
return INF;
}
$p = 10;
while($number > ($p*=10));
return $p;
}
echo n(1), "\n";
//output 10
echo n(232), "\n";
//output 1000
echo n(89289382), "\n";
//output 100000000
echo n(INF), "\n";
// output INF
echo n(-INF), "\n";
// throws exception 'InvalidArgumentException' with message 'Number must be greater or equal 1.'
This example does the iterative calculation in PHP userland code. There are some math functions in PHP that can do it inline like pow.

IMEI validation function

Does anybody know a PHP function for IMEI validation?
Short solution
You can use this (witchcraft!) solution, and simply check the string length:
function is_luhn($n) {
$str = '';
foreach (str_split(strrev((string) $n)) as $i => $d) {
$str .= $i %2 !== 0 ? $d * 2 : $d;
}
return array_sum(str_split($str)) % 10 === 0;
}
function is_imei($n){
return is_luhn($n) && strlen($n) == 15;
}
Detailed solution
Here's my original function that explains each step:
function is_imei($imei){
// Should be 15 digits
if(strlen($imei) != 15 || !ctype_digit($imei))
return false;
// Get digits
$digits = str_split($imei);
// Remove last digit, and store it
$imei_last = array_pop($digits);
// Create log
$log = array();
// Loop through digits
foreach($digits as $key => $n){
// If key is odd, then count is even
if($key & 1){
// Get double digits
$double = str_split($n * 2);
// Sum double digits
$n = array_sum($double);
}
// Append log
$log[] = $n;
}
// Sum log & multiply by 9
$sum = array_sum($log) * 9;
// Compare the last digit with $imei_last
return substr($sum, -1) == $imei_last;
}
Maybe can help you :
This IMEI number is something like this: ABCDEF-GH-IJKLMNO-X (without “-” characters)
For example: 350077523237513
In our example ABCDEF-GH-IJKLMNO-X:
AB is Reporting Body Identifier such as 35 = “British Approvals Board of Telecommunications (BABT)”
ABCDEF is Type Approval Code
GH is Final Assembly Code
IJKLMNO is Serial Number
X is Check Digit
Also this can help you : http://en.wikipedia.org/wiki/IMEI#Check_digit_computation
If i don't misunderstood, IMEI numbers using Luhn algorithm . So you can google this :) Or you can search IMEI algorithm
Maybe your good with the imei validator in the comments here:
http://www.php.net/manual/en/function.ctype-digit.php#77718
But I haven't tested it
Check this solution
<?php
function validate_imei($imei)
{
if (!preg_match('/^[0-9]{15}$/', $imei)) return false;
$sum = 0;
for ($i = 0; $i < 14; $i++)
{
$num = $imei[$i];
if (($i % 2) != 0)
{
$num = $imei[$i] * 2;
if ($num > 9)
{
$num = (string) $num;
$num = $num[0] + $num[1];
}
}
$sum += $num;
}
if ((($sum + $imei[14]) % 10) != 0) return false;
return true;
}
$imei = '868932036356090';
var_dump(validate_imei($imei));
?>
IMEI validation uses Luhn check algorithm. I found a link to a page where you can validate your IMEI. Furthermore, at the bottom of this page is a piece of code written in JavaScript to show how to calculate the 15th digit of IMEI and to valid IMEI. I might give you some ideas. You can check it out here http://imei.sms.eu.sk/index.html
Here is a jQuery solution which may be of use: https://github.com/madeinstefano/imei-validator
good fun from kasperhartwich
function validateImei($imei, $use_checksum = true) {
if (is_string($imei)) {
if (ereg('^[0-9]{15}$', $imei)) {
if (!$use_checksum) return true;
for ($i = 0, $sum = 0; $i < 14; $i++) {
$tmp = $imei[$i] * (($i%2) + 1 );
$sum += ($tmp%10) + intval($tmp/10);
}
return (((10 - ($sum%10)) %10) == $imei[14]);
}
}
return false;
}

Categories