PHP - Generate a round number according to another number - php

How can generate a round number according to a number in PHP?
Ex: if my number is
235112, then I should get 300000 or
122432, then I should get 200000 or
328522, then I should get 400000 ?

You can use a helper function to have the round-up:
function roundup ($value, $places=0) {
if ($places < 0)
{
$places = 0;
}
$mult = pow(10, $places);
return ceil($mult*$value)/$mult;
}
and use it like roundup($value,-5); to roundup 5 digits

String approach :
$s as string input
$s = ($s[0] === '9' ? '1' . str_repeat('0', strlen($s)) : (((int)$s[0]) + 1) . str_repeat('0', strlen($s) - 1));

modified version of Gardax answer:
<?php
$str = "328522";
function ceiling($number)
{
$strlen = strlen($number);
$significance = "1";
for($i=0; $i<($strlen-1);$i++)
{
$significance .= "0";
}
return ( is_numeric($number) && is_numeric($significance) ) ? (ceil($number/$significance)*$significance) : false;
}
echo ceiling($str);
?>

Related

how to change the color of decimals points in php

how can I change the colors of ONLY decimals of a number in PHP?
this is my function for formatting numbers
function formatNumber($input, $decimals = 'auto', $prefix = '', $suffix = '') {
$input = floatval($input);
$absInput = abs($input);
if ($decimals === 'auto') {
if ($absInput >= 0.01) {
$decimals = 2;
} elseif (0.0001 <= $absInput && $absInput < 0.01) {
$decimals = 4;
} elseif (0.000001 <= $absInput && $absInput < 0.0001) {
$decimals = 6;
} elseif ($absInput < 0.000001) {
$decimals = 8;
}
}
if($input>1000000000000000){
$result = ROUND(($input/1000000000000000),2).' TH ';
}elseif($input>1000000000000){
$result = ROUND(($input/1000000000000),2).' T ';
}elseif($input>1000000000){
$result = ROUND(($input/1000000000),2).' B ';
}elseif($input>1000000) {
$result = ROUND(($input / 1000000), 2) . ' M ';
} else {
$result = number_format($input, $decimals, config('decimal-separator','.'), config('thousand-separator', ',')) ;
}
return ($prefix ? $prefix : '') . $result. ($suffix ? $suffix : '');
}
and I use it like that
<?php echo formatNumber($chart['assist'], 2)?>
i want my decimals with a different color... can i use css there or add classes?
Here is an example of what I meant in my comment by manipulate the string:
<?php
$n = 123.456;
$whole = floor($n); // 123
$fraction = $n - $whole; // .456
//echo str_replace('.', '<span class="colorme">.</span>', $n);
echo $whole . '<span class="colorme">.</span>' . substr($fraction, strpos($fraction, '.')+1);
//Simply do a string replace on the decimal point.
UPDATED break out parts, concatenate.
A client side approach with Javascript (with some jQuery) would be something like:
$('#myDiv').each(function () {
$(this).html($(this).html().replace(/\./g, '<span class="colorme">.</span>'));
//or decimal point and decimal number part...
$(this).html($(this).html().replace(/\.([0-9]+)/g, '<span class="colorme">.$1</span>'));
});
Remember that other locales don't always use . for divider.
So with your existing code, you could do something like:
$dec_point = config('decimal-separator','.');
$wrapped_dec_point = "<span class='dec_point'>{$dec_point}</span>";
$result = number_format($input, $decimals, $wrapped_dec_point, config('thousand-separator', ',')) ;
and then of course, for your CSS, you would just need
.dec_point {
color: magenta;
}
Here is shorter solution
$n = 123.456;
$nums = explode(".",$n);
echo $nums[0] . '<span class="colorme">.' . $nums[1] . '</span>';

converting hexadecimal to decimal php

I have to convert hexadecimal to decimal with PHP (without using hexdec) for my homework, but my code does not convert properly.
For example, when I use the function HexToDez ("1F4");, the answer should be 500, not 1.
Why is it not working?
the code
<?php
function Replace ($i)
{
switch (strToLower ($i))
{
case "a" : return 10;
case "b" : return 11;
case "c" : return 12;
case "d" : return 13;
case "e" : return 14;
case "f" : return 15;
default : return $i;
}
}
function HexToDez($i) # 1F4
{
$input=$i;
$num=strlen ($input) ;
$pos=0;
$output="";
$hochzahl="";
while($pos<$num)
{
$mid = substr ($input, $pos, 1);
$pos++;
return $end=Replace ($mid);
}
while ($end != 0){
$zahl = $input%10;
$output += $zahl*pow(16, $hochzahl);
$end = $end/10;
$hochzahl++;
}
echo $output;
}
?>
here is "classic" algorithm for you to consider, check the comments:
function HexToDez($s) {
$output = 0;
for ($i=0; $i<strlen($s); $i++) {
$c = $s[$i]; // you don't need substr to get 1 symbol from string
if ( ($c >= '0') && ($c <= '9') )
$output = $output*16 + ord($c) - ord('0'); // two things: 1. multiple by 16 2. convert digit character to integer
elseif ( ($c >= 'A') && ($c <= 'F') ) // care about upper case
$output = $output*16 + ord($s[$i]) - ord('A') + 10; // note that we're adding 10
elseif ( ($c >= 'a') && ($c <= 'f') ) // care about lower case
$output = $output*16 + ord($c) - ord('a') + 10;
}
return $output;
}
echo HexToDez("1F4"); // outputs 500
also, you can use intval function to do the same, just convert your number into hex representation, like 0x###
function HexToDez($s) {
return intval('0x'.$s, 16);
}

How to remove zeroes at the end of decimal part of a float number?

I have in database product prices with 4 digits in decimal part, i.e;
4.5000
0.0050
5.0000
I want to show on the website these prices with minimum 2 decimal digits (without rounding), i.e;
4.50
0.005
5.00
I tried number_format, but it still leaves 4 digits in decimal part.
And also I need to use thousands separator on a base part of that number and own delimiter of decimal part.
How to do this?
function trimDecimalZero($num, $delim = ',', $tsep = ' ') {
#list($base, $decimals) = explode('.',
rtrim(number_format((float) $num, 4, '.', $tsep), '0'));
if (intval($decimals)) {
return sprintf('%s%s%s',
$base, $delim, strlen($decimals) < 2 ? $decimals .'0' : $decimals);
}
return sprintf('%s%s%02d', $base, $delim, $decimals);
}
$nums = [4.5000, 0.0050, 5.0000];
foreach ($nums as $num) {
var_dump(trimDecimalZero($num));
}
Result as expected;
string(4) "4,50"
string(5) "0,005"
string(4) "5,00"
Try with -
echo number_format('4.5000', 2);
Update
$v = (float)'0.0050';
$newV = explode('.', $v);
if(strlen($newV[1]) < 2) {
$v = number_format($v, 2);
}
echo $v;
For future reference, once again I modified my answer and yes, it outputs expected results:
function trimDecimalZero($number) {
$number += 0;
if(strlen(substr(strrchr($number, "."),1)) < 2) {
$number = sprintf("%0.2f", $number);
}
return $number;
}
echo trimDecimalZero(4.5000); //4.50
echo trimDecimalZero(0.00050); //0.00005
echo trimDecimalZero(5.0000); //5.00
Hope this would help future readers!
I guess that if it is for showing purposes, you could do something like this:
$number= 4.500000;
$number.= 'x';
$length = strlen($number);
$new_number = rtrim($number, '0x');
if (strlen($new_number) < $length) {
$new_number .= '0';
}
echo $new_number;

Converting float decimal to fraction

I am trying to convert calculations keyed in by users with decimal results into fractions. For e.g.; 66.6666666667 into 66 2/3. Any pointers?
Thanx in advance
Continued fractions can be used to find rational approximations to real numbers that are "best" in a strict sense. Here's a PHP function that finds a rational approximation to a given (positive) floating point number with a relative error less than $tolerance:
<?php
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
printf("%s\n", float2rat(66.66667)); # 200/3
printf("%s\n", float2rat(sqrt(2))); # 1393/985
printf("%s\n", float2rat(0.43212)); # 748/1731
I have written more about this algorithm and why it works, and even a JavaScript demo here: https://web.archive.org/web/20180731235708/http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/
Farey fractions can be quite useful in this case.
They can be used to convert any decimal into a fraction with the lowest possible denominator.
Sorry - I don't have a prototype in PHP, so here's one in Python:
def farey(v, lim):
"""No error checking on args. lim = maximum denominator.
Results are (numerator, denominator); (1, 0) is 'infinity'."""
if v < 0:
n, d = farey(-v, lim)
return (-n, d)
z = lim - lim # Get a "zero of the right type" for the denominator
lower, upper = (z, z+1), (z+1, z)
while True:
mediant = (lower[0] + upper[0]), (lower[1] + upper[1])
if v * mediant[1] > mediant[0]:
if lim < mediant[1]:
return upper
lower = mediant
elif v * mediant[1] == mediant[0]:
if lim >= mediant[1]:
return mediant
if lower[1] < upper[1]:
return lower
return upper
else:
if lim < mediant[1]:
return lower
upper = mediant
Converted Python code in answer from #APerson241 to PHP
<?php
function farey($v, $lim) {
// No error checking on args. lim = maximum denominator.
// Results are array(numerator, denominator); array(1, 0) is 'infinity'.
if($v < 0) {
list($n, $d) = farey(-$v, $lim);
return array(-$n, $d);
}
$z = $lim - $lim; // Get a "zero of the right type" for the denominator
list($lower, $upper) = array(array($z, $z+1), array($z+1, $z));
while(true) {
$mediant = array(($lower[0] + $upper[0]), ($lower[1] + $upper[1]));
if($v * $mediant[1] > $mediant[0]) {
if($lim < $mediant[1])
return $upper;
$lower = $mediant;
}
else if($v * $mediant[1] == $mediant[0]) {
if($lim >= $mediant[1])
return $mediant;
if($lower[1] < $upper[1])
return $lower;
return $upper;
}
else {
if($lim < $mediant[1])
return $lower;
$upper = $mediant;
}
}
}
// Example use:
$f = farey(66.66667, 10);
echo $f[0], '/', $f[1], "\n"; # 200/3
$f = farey(sqrt(2), 1000);
echo $f[0], '/', $f[1], "\n"; # 1393/985
$f = farey(0.43212, 2000);
echo $f[0], '/', $f[1], "\n"; # 748/1731
Based upon #Joni's answer, here is what I used to pull out the whole number.
function convert_decimal_to_fraction($decimal){
$big_fraction = float2rat($decimal);
$num_array = explode('/', $big_fraction);
$numerator = $num_array[0];
$denominator = $num_array[1];
$whole_number = floor( $numerator / $denominator );
$numerator = $numerator % $denominator;
if($numerator == 0){
return $whole_number;
}else if ($whole_number == 0){
return $numerator . '/' . $denominator;
}else{
return $whole_number . ' ' . $numerator . '/' . $denominator;
}
}
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
Based on #APerson's and #Jeff Monteiro's answers I've created PHP version of Farey fractions that will be simplified to whole values with fractions with lowest possible denominator:
<?php
class QuantityTransform
{
/**
* #see https://stackoverflow.com/questions/14330713/converting-float-decimal-to-fraction
*/
public static function decimalToFraction(float $decimal, $glue = ' ', int $limes = 10): string
{
if (null === $decimal || $decimal < 0.001) {
return '';
}
$wholeNumber = (int) floor($decimal);
$remainingDecimal = $decimal - $wholeNumber;
[$numerator, $denominator] = self::fareyFraction($remainingDecimal, $limes);
// Values rounded to 1 should be added to base value and returned without fraction part
if (is_int($simplifiedFraction = $numerator / $denominator)) {
$wholeNumber += $simplifiedFraction;
$numerator = 0;
}
return (0 === $wholeNumber && 0 === $numerator)
// Too small values will be returned in original format
? (string) $decimal
// Otherwise let's format value - only non-0 whole value / fractions will be returned
: trim(sprintf(
'%s%s%s',
(string) $wholeNumber ?: '',
$wholeNumber > 0 ? $glue : '',
0 === $numerator ? '' : ($numerator . '/' . $denominator)
));
}
/**
* #see https://stackoverflow.com/a/14330799/842480
*
* #return int[] Numerator and Denominator values
*/
private static function fareyFraction(float $value, int $limes): array
{
if ($value < 0) {
[$numerator, $denominator] = self::fareyFraction(-$value, $limes);
return [-$numerator, $denominator];
}
$zero = $limes - $limes;
$lower = [$zero, $zero + 1];
$upper = [$zero + 1, $zero];
while (true) {
$mediant = [$lower[0] + $upper[0], $lower[1] + $upper[1]];
if ($value * $mediant[1] > $mediant[0]) {
if ($limes < $mediant[1]) {
return $upper;
}
$lower = $mediant;
} elseif ($value * $mediant[1] === $mediant[0]) {
if ($limes >= $mediant[1]) {
return $mediant;
}
if ($lower[1] < $upper[1]) {
return $lower;
}
return $upper;
} else {
if ($limes < $mediant[1]) {
return $lower;
}
$upper = $mediant;
}
}
}
}
Then you san use it like:
QuantityTransform::decimalToFraction(0.06); // 0.06
QuantityTransform::decimalToFraction(0.75); // 3/4
QuantityTransform::decimalToFraction(1.75, ' and '); // 1 and 3/4
QuantityTransform::decimalToFraction(2.33, ' and '); // 2 and 1/3
QuantityTransform::decimalToFraction(2.58, ' ', 5); // 2 3/5
QuantityTransform::decimalToFraction(2.58, ' & ', 10); // 2 & 4/7
QuantityTransform::decimalToFraction(1.97); // 2
Here is my approach to this problem. Works fine with rational numbers.
function dec2fracso($dec){
//Negative number flag.
$num=$dec;
if($num<0){
$neg=true;
}else{
$neg=false;
}
//Extracts 2 strings from input number
$decarr=explode('.',(string)$dec);
//Checks for divided by zero input.
if($decarr[1]==0){
$decarr[1]=1;
$fraccion[0]=$decarr[0];
$fraccion[1]=$decarr[1];
return $fraccion;
}
//Calculates the divisor before simplification.
$long=strlen($decarr[1]);
$div="1";
for($x=0;$x<$long;$x++){
$div.="0";
}
//Gets the greatest common divisor.
$x=(int)$decarr[1];
$y=(int)$div;
$gcd=gmp_strval(gmp_gcd($x,$y));
//Calculates the result and fills the array with the correct sign.
if($neg){
$fraccion[0]=((abs($decarr[0])*($y/$gcd))+($x/$gcd))*(-1);
}else{
$fraccion[0]=(abs($decarr[0])*($y/$gcd))+($x/$gcd);
}
$fraccion[1]=($y/$gcd);
return $fraccion;
}
Sometimes it is necessary to treat only the decimals of a float. So I created a code that uses the function created by #Joni to present a format that is quite common in culinary recipes, at least in Brazil.
So instead of using 3/2 which is the result for 1.5, using the function I created it is possible to present the value 1 1/2, and if you want, you can also add a string to concatenate the values, creating something like "1 and 1/2 ".
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
function float2fraction($float, $concat = ' '){
// ensures that the number is float,
// even when the parameter is a string
$float = (float)$float;
if($float == 0 ){
return $float;
}
// when float between -1 and 1
if( $float > -1 && $float < 0 || $float < 1 && $float > 0 ){
$fraction = float2rat($float);
return $fraction;
}
else{
// get the minor integer
if( $float < 0 ){
$integer = ceil($float);
}
else{
$integer = floor($float);
}
// get the decimal
$decimal = $float - $integer;
if( $decimal != 0 ){
$fraction = float2rat(abs($decimal));
$fraction = $integer . $concat . $fraction;
return $fraction;
}
else{
return $float;
}
}
}
Usage e.g:
echo float2fraction(1.5);
will return "1 1/2"

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