Since i'm more of a "noob" at PHP than i'd hope, Is it possible to inverse the following function for example:
public function baseID($resourceid){
$rid = $resourceid;
$version = 0;
while ($rid > 16777216){
$version++;
if ($version == 1){
//the constant applied to all items
$rid -= 1342177280;
}elseif ($version == 2){
//the value added to the first updated version
$rid -= 50331648;
}else{
//the value added on all subsequent versions
$rid -= 16777216;
}
}
//$returnable = array('baseID'=>$rid,'version'=>$version);
return $rid;
}
Would it be possible to input the "baseID" and return a "resourceID" instead of the current way ?
I apologize if this is the wrong place to be asking such question
Not really. Your function returns the same value for all rids that are of the form:
5 * 2^28 + (3 + n) * 2^24
Where n is a positive integer.
>>> baseID(5 * 2**28 + (3 + 1) * 2**24)
16777216
>>> baseID(5 * 2**28 + (3 + 2) * 2**24)
16777216
>>> baseID(5 * 2**28 + (3 + 3) * 2**24)
16777216
So given just 16777216, you won't be able to determine what went into your function.
This function only works to a limited range, however at a certain point the resource IDs will start returning the same results.
public function resourceID($baseid){
$bid = $baseid;
$version = 0;
while ($bid <= 16777216){
++$version;
if ($version === 1){
$bid += 1342177280;
} elseif ($version === 2){
$bid += 50331648;
} else {
$bid += 16777216;
}
}
return $bid;
}
Related
I have found a PHP script github ISBN-Calc Routine to perform the ISBN-10 checksum calculation:
<?php
/**
* Calculate ISBN checksum
*
* #param string $isbn
* #return integer
*/
function isbn_checksum($isbn) {
$sum = 0; $isbn = str_split(preg_replace('/[^\d]/', '', $isbn));
foreach($isbn as $key => $z) {
if($key >= 12) break;
$sum += ($key % 2) ? $z * 3 : $z;
}
$checksum = (10 - $sum % 10);
return ($checksum == 10) ? 0 : $checksum;
}
But f.e for my ISBN-10: 0470173424 I get Checksum: 0with this github script.
Accoring to ISBN online checker the checksum should be 4 as is it in the ISBN. Can anyone here provide me with the correct PHP routine, please?
Thanks
That function is for calculating an ISBN-13 check digit, not ISBN-10 - that's why it breaks the loop after the 12th character.
The algorithm for ISBN-10 is different, and requires multiplying the first 9 digits of the number by 10 down to 2. The difference between that sum and the next multiple of 11 is the check-digit. For your example, this would be:
(10 * 0) +
(9 * 4) +
(8 * 7) +
(7 * 0) +
(6 * 1) +
(5 * 7) +
(4 * 3) +
(3 * 4) +
(2 * 2) = 161.
The next multiple of 11 is 165, so the check-digit should be 4 (as you say). In the case where the check-digit would be 10, X is used. We can model this in PHP like this:
function isbn10($isbn) {
$isbn = preg_replace('/[^\d]/', '', $isbn);
$digits = str_split(substr($isbn, 0, 9));
$sum = 0;
foreach ($digits as $index => $digit) {
$sum += (10 - $index) * $digit;
}
$check = 11 - ($sum % 11);
return ($check === 10) ? 'X' : $check;
}
echo isbn10('047017342');
4
You can see this working here: https://eval.in/1039654
The previously marked answer is close but incomplete.
Specifically this portion:
$check = 11 - ($sum % 11); // This can output 1,2,3,4,5,6,7,8,9,10,11 not 0
return ($check === 10) ? 'X' : $check; // This is incomplete does not address 11
The code does not deal with the situation where 11 - 0 = 11. I have tried to clarify it below.
function isbn10($isbn)
{
$isbn = preg_replace('/[^\d]/', '', $isbn);
$digits = str_split(substr($isbn, 0, 9));
$sum = 0;
foreach ($digits as $index => $digit)
{
$sum += (10 - $index) * $digit;
}
$check = 11 - ($sum % 11);
// $check may hold either 10 or 11, but not 0
// 10 becomes X, 11 becomes 0 -- output is 1 character only
if ($check == 10)
{
$check = 'X';
}
elseif ($check == 11)
{
$check = '0';
}
return $check;
}
An example ISBN where the earlier answer fails is 0134093410
There is an library from GitHub: https://github.com/Fale/isbn
There is a function called "Check":
Initialization:
$isbn = new Isbn\Isbn();
Check values: (Example)
$isbn->check->is10('888183718'); // Will return false
$isbn->check->is13('9788889527191'); // Will return true
$isbn->check->is13('978888952719'); // Will return false
You can download the library from the given link.
Maybe that helps a bit.
Have a nice weekend!
If you want to check if the ISBN-10 is correct
Validate ISBN-10
<?php
function isValidIsbn10($isbn) {
$check = 0;
for ($i = 0; $i < 10; $i++) {
if ('x' === strtolower($isbn[$i])) {
$check += 10 * (10 - $i);
} elseif (is_numeric($isbn[$i])) {
$check += (int)$isbn[$i] * (10 - $i);
} else {
return false;
}
}
return (0 === ($check % 11)) ? 1 : false;
}
var_dump( isValidIsbn10('0470173424') );
Source: https://stackoverflow.com/a/14096142/5201919
Will show
1 for true
Demo
https://eval.in/1053913
I need to return a result of (1 / n!) * (1! + 2! + 3! + ... + n!), n>=1.
This is a CodeWars challenge! The code below returns 1.146652 for n = 8, but the correct result is 1.1466510000000001 or 1.146651.
How can I truncate this number correctly?
function factorial($val){
$factor = 1;
for($i=1;$i<=$val;$i++){
$factor *= $i;
}
return $factor;
}
function going($n) {
$val = 1/factorial($n);
$somatorio = 0;
for($i=1;$i<=$n;$i++){
$somatorio += factorial($i);
}
return round($val * $somatorio,6);
}
How can I calculate the n-th root of an integer using PHP/GMP?
Although I found a function called gmp_root(a, nth) in the PHP source, it seems that this function has not been published in any release yet*: http://3v4l.org/8FjU7
*) 5.6.0alpha2 being the most recent one at the time of writing
Original source: Calculating Nth root with bcmath in PHP – thanks and credits to HamZa!
I've rewritten the code to use GMP instead of BCMath:
function gmp_nth_root($num, $n) {
if ($n < 1) return 0; // we want positive exponents
if ($num <= 0) return 0; // we want positive numbers
if ($num < 2) return 1; // n-th root of 1 or 2 give 1
// g is our guess number
$g = 2;
// while (g^n < num) g=g*2
while (gmp_cmp(gmp_pow($g, $n), $num) < 0) {
$g = gmp_mul($g, 2);
}
// if (g^n==num) num is a power of 2, we're lucky, end of job
if (gmp_cmp(gmp_pow($g, $n), $num) == 0) {
return $g;
}
// if we're here num wasn't a power of 2 :(
$og = $g; // og means original guess and here is our upper bound
$g = gmp_div($g, 2); // g is set to be our lower bound
$step = gmp_div(gmp_sub($og, $g), 2); // step is the half of upper bound - lower bound
$g = gmp_add($g, $step); // we start at lower bound + step , basically in the middle of our interval
// while step != 1
while (gmp_cmp($step, 1) > 0) {
$guess = gmp_pow($g, $n);
$step = gmp_div($step, 2);
$comp = gmp_cmp($guess, $num); // compare our guess with real number
if ($comp < 0) { // if guess is lower we add the new step
$g = gmp_add($g, $step);
} else if ($comp == 1) { // if guess is higher we sub the new step
$g = gmp_sub($g, $step);
} else { // if guess is exactly the num we're done, we return the value
return $g;
}
}
// whatever happened, g is the closest guess we can make so return it
return $g;
}
I've been searching all over and cannot find anything about this.
I'm looking for a function that will convert a Z-Score to a Probability using a two tailed table, preferably in PHP.
(Like this one: http://www.sjsu.edu/faculty/gerstman/StatPrimer/z-two-tails.pdf)
My only other option is to make an array based on that table and comparing the Z-Score.. There must be a better way.
Edit:
Below is a slab of code found on the PHP.net statistics function page. These functions are really poorly documented.
The functions below will accurately calculate a one-tailed z-score into a probability.
function erf($x)
{
$pi = 3.1415927;
$a = (8*($pi - 3))/(3*$pi*(4 - $pi));
$x2 = $x * $x;
$ax2 = $a * $x2;
$num = (4/$pi) + $ax2;
$denom = 1 + $ax2;
$inner = (-$x2)*$num/$denom;
$erf2 = 1 - exp($inner);
return sqrt($erf2);
}
function cdf($n)
{
if($n < 0)
{
return (1 - erf($n / sqrt(2)))/2;
}
else
{
return (1 + erf($n / sqrt(2)))/2;
}
}
Found a solution:
function erf($x)
{
$pi = 3.1415927;
$a = (8*($pi - 3))/(3*$pi*(4 - $pi));
$x2 = $x * $x;
$ax2 = $a * $x2;
$num = (4/$pi) + $ax2;
$denom = 1 + $ax2;
$inner = (-$x2)*$num/$denom;
$erf2 = 1 - exp($inner);
return sqrt($erf2);
}
function cdf($n)
{
return (1 - erf($n / sqrt(2)))/2;
//I removed the $n < 0 test which inverses the +1/-1
}
function cdf_2tail($n)
{
return 2*cdf($n);
//After a little more digging around, the two tail test is simply 2 x the cdf.
}
I tested my results against: http://vassarstats.net/tabs.html#z and the z-score table.
It is correct to 0.1%
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;
}