Laravel format to 1 decimal place - php

#if($user->dettagli->facebook_follower >= 1000 && $user->dettagli->facebook_follower <= 999999)
<?php
echo(round($user->dettagli->facebook_follower, 5,PHP_ROUND_HALF_DOWN) . "K");
?>
{{$user->dettagli->facebook_follower / 1000}} K
#endif
Hi could someone please help me. I am using Laravel and trying to display a users Facebook follower count, but I got a little stuck with something. I am taking their int at for example 1589 followers and trying to return in the blade "1.5k". On screen I return either 1589k with this php call or 1.589k. How do I get that number to one decimal place and become only 1.5k??
thank you!

As per the docs
Returns the rounded value of val to specified precision (number of digits after the decimal point). precision can also be negative or zero (default).
You are specifying a precision of 5. You should change this to 1.
Change your function call to:
echo(round($user->dettagli->facebook_follower, 1, PHP_ROUND_HALF_DOWN) . "K");
EDIT: I mis-read the question. This is a function that should handle numbers into the millions.
You would need to use laravel-twigbridge to make the function available in your templates though.
function pretty_number(int $n): string {
$prettyN = $n;
$suffix = '';
$len = strlen((string) $n);
$suffixes = ['K', 'M'];
foreach ($suffixes as $s) {
if ($n < 1000) {
break;
}
$suffix = $s;
$n = $n / 1000;
$prettyN = number_format($n, 1);
}
return $prettyN . $suffix;
}
echo pretty_number(100); // 100
echo pretty_number(999); // 99
echo pretty_number(1589); // 1.6K
echo pretty_number(1600); // 1.6K
echo pretty_number(1589300); // 1.6M

You can use the NumberFormatter. This can be defined in a global place so you only need to use the third line in your blade view.
$a = new \NumberFormatter("en-US", \NumberFormatter::DECIMAL);
$a->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, 1);
echo $a->format($user->dettagli->facebook_follower);

Related

Is there a specific function that allows me to round up to a specific decimal number in PHP

I have a number that needs to be rounded up to a specific decimal, is there any function in PHP to do that?
I need every number (which reflects an amount of money) to have a specific decimal number.
For example:
The decimal needs to be 25, so if I got $ 25.50 I need it to be $ 26.25, and if I got $ 25.10 it needs to be $ 25.25.
I've checked PHP round(), and specifically ceil(), and I've come across this answer in Python, but I'm not sure it applies to my case, because what I need is different.
Any ideas? Even pseudo code as a tip on where to start will help me. Thanks!
I think you need a custom function, something like this:
function my_round($number, $decimal = 0.25) {
$result = floor($number) + $decimal;
if ($result < $number) $result = ceil($number) + $decimal;
return $result;
}
print my_round(25.50);
I modified this answer for your case:
<?php
function roundUp($number){
$int = floor($number);
$float = $number-$int;
if ($float*10 < 2.5)
$result = $int;
else
$result = ceil($number);
$result+= 0.25;
echo $number." becomes ".$result."\n";
}
roundUp(25.50);
roundUp(25.10);
Look for demo here
Following axiac's advice mentioned in the comments and following this thread, the best way to deal with floating point numbers in the context of currencies, is to treat the dollars and cents' values as 2 separate entities.
One way I can think of it to split the numbers before and after the decimal into 2 separate variables and process accordingly.
<?php
function customRound($amount){
$amount = strval($amount);
if(preg_match('/(\d+)\.?(\d{1,2})?/', $amount, $matches) !== 1){
throw new \Exception("Invalid amount.");
}
$dollars = intval($matches[1]);
$cents = intval($matches[2] ?? 0);
if($cents < 10) $cents *= 10;
if($cents <= 25) return $dollars . ".25";
return ($dollars + 1) . ".25";
}
$tests = [25.51,25.49,26.25,25.10,25.49];
foreach ($tests as $test){
echo $test," => ",customRound($test),PHP_EOL;
}
Here's another approach:
<?php
function roundUp($number, $decimal=0.25){
$dollars = floor($number);
$cents = $number - $dollars;
if($cents > $decimal) {
++$dollars;
}
return $dollars + $decimal;
}
echo roundUp(25.50).PHP_EOL;
echo roundUp(25.10);

Could not generate 6 digit random number including date time using PHP

I need one help . I need to generate random number including date and time using PHP. I am explaining my code below.
$random=generateRandom();
echo $random;
function generateRandom() {
$result = base_convert((float) rand() / (float) getrandmax() * round(microtime(true) * 1000),6, 36);
return $result;
}
The above function giving the 3 digit output. Here i need to generate up to 6 digit. Please help me.
Here it is with microtime :
$random=generateRandom();
echo $random;
function generateRandom() {
$numbers = str_split((string)(int)microtime(true));
shuffle($numbers);
$rand = '';
foreach (array_rand($numbers, 6) as $k) $rand .= $numbers[$k];
return $rand;
}
Conversion are here to eliminated the dot character.

php random x digit number

I need to create a random number with x amount of digits.
So lets say x is 5, I need a number to be eg. 35562
If x is 3, then it would throw back something like; 463
Could someone show me how this is done?
You can use rand() together with pow() to make this happen:
$digits = 3;
echo rand(pow(10, $digits-1), pow(10, $digits)-1);
This will output a number between 100 and 999. This because 10^2 = 100 and 10^3 = 1000 and then you need to subtract it with one to get it in the desired range.
If 005 also is a valid example you'd use the following code to pad it with leading zeros:
$digits = 3;
echo str_pad(rand(0, pow(10, $digits)-1), $digits, '0', STR_PAD_LEFT);
I usually just use RAND() http://php.net/manual/en/function.rand.php
e.g.
rand ( 10000 , 99999 );
for your 5 digit random number
Here is a simple solution without any loops or any hassle which will
allow you to create random string with characters, numbers or even with special symbols.
$randomNum = substr(str_shuffle("0123456789"), 0, $x);
where $x can be number of digits
Eg.
substr(str_shuffle("0123456789"), 0, 5);
Results after a couple of executions
98450
79324
23017
04317
26479
You can use the same code to generate random string also, like this
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyzABCDEFGHIJKLMNOPQRSTVWXYZ"), 0, $x);
Results with $x = 11
FgHmqpTR3Ox
O9BsNgcPJDb
1v8Aw5b6H7f
haH40dmAxZf
0EpvHL5lTKr
You can use rand($min, $max) for that exact purpose.
In order to limit the values to values with x digits you can use the following:
$x = 3; // Amount of digits
$min = pow(10,$x);
$max = pow(10,$x+1)-1);
$value = rand($min, $max);
Treat your number as a list of digits and just append a random digit each time:
function n_digit_random($digits) {
$temp = "";
for ($i = 0; $i < $digits; $i++) {
$temp .= rand(0, 9);
}
return (int)$temp;
}
Or a purely numerical solution:
function n_digit_random($digits)
return rand(pow(10, $digits - 1) - 1, pow(10, $digits) - 1);
}
the simplest way i can think of is using rand function with str_pad
<?php
echo str_pad(rand(0,999), 5, "0", STR_PAD_LEFT);
?>
In above example , it will generate random number in range 0 to 999.
And having 5 digits.
function random_numbers($digits) {
$min = pow(10, $digits - 1);
$max = pow(10, $digits) - 1;
return mt_rand($min, $max);
}
Tested here.
rand(1000, 9999); works more faster than x4 times rand(0,9);
benchmark:
rand(1000, 9999) : 0.147 sec.
rand(0,9)x4 times : 0.547 sec.
both functions was running in 100000 iterations to make results more explicit
Well you can use as simple php function mt_rand(2000,9000) which can generate a 4 digit random number
mt_rand(2000,9000)
You can generate any x-digit random number with mt_rand() function.
mt_rand() is faster than rand().
Syntax : mt_rand() or mt_rand($min , $max).
Example : <?php echo mt_rand(); ?>
read more
do it with a loop:
function randomWithLength($length){
$number = '';
for ($i = 0; $i < $length; $i++){
$number .= rand(0,9);
}
return (int)$number;
}
rand or mt_rand will do...
usage:
rand(min, max);
mt_rand(min, max);
function random_number($size = 5)
{
$random_number='';
$count=0;
while ($count < $size )
{
$random_digit = mt_rand(0, 9);
$random_number .= $random_digit;
$count++;
}
return $random_number;
}
Following is simple method to generate specific length verification code. Length can be specified, by default, it generates 4 digit code.
function get_sms_token($length = 4) {
return rand(
((int) str_pad(1, $length, 0, STR_PAD_RIGHT)),
((int) str_pad(9, $length, 9, STR_PAD_RIGHT))
);
}
echo get_sms_token(6);
this simple script will do
$x = 4;//want number of digits for the random number
$sum = 0;
for($i=0;$i<$x;$i++)
{
$sum = $sum + rand(0,9)*pow(10,$i);
}
echo $sum;
This is another simple solution to generate random number of N digits:
$number_of_digits = 10;
echo substr(number_format(time() * mt_rand(),0,'',''),0,$number_of_digits);
Check it here: http://codepad.org/pyVvNiof
function rand_number_available($already_mem_array,$boundary_min,$boundary_max,$digits_num)
{
$already_mem_array_dim = count($already_mem_array); // dimension of array, that contain occupied elements
// --- creating Boundaries and possible Errors
if( empty($digits_num) ){
$boundary_dim = $boundary_max - $boundary_min;
if($boundary_dim <= 0){
$error = -1; // Error that might happen. Difference between $boundary_max and $boundary_min must be positive
}else{
$error = -2; // Error that might happen. All numbers between, $boundary_min and $boundary_max , are occupied, by $already_mem_array
}
}else{
if($digits_num < 0){ // Error. If exist, $digits_num must be, 1,2,3 or higher
$error = -3;
}elseif($digits_num == 1){ // if 'one-figure' number
$error = -4; // Error that might happen. All 'one-figure' numbers are occupied, by $already_mem_array
$boundary_min = 0;
$boundary_max = 9;
$boundary_dim = $boundary_max-$boundary_min;
}elseif($digits_num == 2){ // if 'two-figure' number
$error = -5; // Error that might happen. All 'two-figure' numbers are occupied, by $already_mem_array
$boundary_min = 10;
$boundary_max = 99;
$boundary_dim = $boundary_max-$boundary_min;
}elseif($digits_num>2){ // if 'X-figure' number. X>2
$error = -6; // Error that might happen. All 'X-figure' numbers are occupied, by $already_mem_array. Unlikely to happen
$boundary_min = pow(10, $digits_num-1); // stepenovanje - graduation
$boundary_max = pow(10, $digits_num)-1;
$boundary_dim = $boundary_max-$boundary_min;
}
}
// -------------------------------------------------------------------
// --- creating response ---------------------------------------------
if( ($already_mem_array_dim <= $boundary_dim) && $boundary_dim>0 ){ // go here only if, there are AVAILABLE numbers to extract, and [difference] $boundary_dim , is positive
do{
$num = rand($boundary_min,$boundary_max);
}while( in_array($num, $already_mem_array) );
$result = $num;
}else{
$result = $error; // Limit that happened
}
return $result;
// -------------------------------------------------------------------
}
This function works perfectly with no repeats and desired number of digits.
$digits = '';
function randomDigits($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0; $i < $length; $i++){
global $digits;
$digits .= $numbers[$i];
}
return $digits;
}
You can call the function and pass the number of digits for example:
randomDigits(4);
sample results:
4957 8710 6730 6082 2987 2041 6721
Original script got from this gist
Please not that rand() does not generate a cryptographically secure value according to the docs:
http://php.net/manual/en/function.rand.php
This function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using random_int(), random_bytes(), or openssl_random_pseudo_bytes() instead.
Instead it is better to use random_int(), available on PHP 7 (See: http://php.net/manual/en/function.random-int.php).
So to extend #Marcus's answer, you should use:
function generateSecureRandomNumber($digits): int {
return random_int(pow(10, $digits - 1), pow(10, $digits) - 1);
}
function generateSecureRandomNumberWithPadding($digits): string {
$randomNumber = random_int(0, pow(10, $digits) - 1);
return str_pad($randomNumber, $digits, '0', STR_PAD_LEFT);
}
Note that using rand() is fine if you don't need a secure random number.
The following code generates a 4 digits random number:
echo sprintf( "%04d", rand(0,9999));
you people really likes to complicate things :)
the real problem is that the OP wants to, probably, add that to the end of some really big number. if not, there is no need I can think of for that to be required. as left zeros in any number is just, well, left zeroes.
so, just append the larger portion of that number as a math sum, not string.
e.g.
$x = "102384129" . complex_3_digit_random_string();
simply becomes
$x = 102384129000 + rand(0, 999);
done.

How to round down to the nearest significant figure in php

Is there any slick way to round down to the nearest significant figure in php?
So:
0->0
9->9
10->10
17->10
77->70
114->100
745->700
1200->1000
?
$numbers = array(1, 9, 14, 53, 112, 725, 1001, 1200);
foreach($numbers as $number) {
printf('%d => %d'
, $number
, $number - $number % pow(10, floor(log10($number)))
);
echo "\n";
}
Unfortunately this fails horribly when $number is 0, but it does produce the expected result for positive integers. And it is a math-only solution.
Here's a pure math solution. This is also a more flexible solution if you ever wanted to round up or down, and not just down. And it works on 0 :)
if($num === 0) return 0;
$digits = (int)(log10($num));
$num = (pow(10, $digits)) * floor($num/(pow(10, $digits)));
You could replace floor with round or ceil. Actually, if you wanted to round to the nearest, you could simplify the third line even more.
$num = round($num, -$digits);
If you do want to have a mathy solution, try this:
function floorToFirst($int) {
if (0 === $int) return 0;
$nearest = pow(10, floor(log($int, 10)));
return floor($int / $nearest) * $nearest;
}
Something like this:
$str = (string)$value;
echo (int)($str[0] . str_repeat('0', strlen($str) - 1));
It's totally non-mathy, but I would just do this utilizing sting length... there's probably a smoother way to handle it but you could acomplish it with
function significant($number){
$digits = count($number);
if($digits >= 2){
$newNumber = substr($number,0,1);
$digits--;
for($i = 0; $i < $digits; $i++){
$newNumber = $newNumber . "0";
}
}
return $newNumber;
}
A math based alternative:
$mod = pow(10, intval(round(log10($value) - 0.5)));
$answer = ((int)($value / $mod)) * $mod;
I know this is an old thread but I read it when looking for inspiration on how to solve this problem. Here's what I came up with:
class Math
{
public static function round($number, $numberOfSigFigs = 1)
{
// If the number is 0 return 0
if ($number == 0) {
return 0;
}
// Deal with negative numbers
if ($number < 0) {
$number = -$number;
return -Math::sigFigRound($number, $numberOfSigFigs);
}
return Math::sigFigRound($number, $numberOfSigFigs);
}
private static function sigFigRound($number, $numberOfSigFigs)
{
// Log the number passed
$log = log10($number);
// Round $log down to determine the integer part of the log
$logIntegerPart = floor($log);
// Subtract the integer part from the log itself to determine the fractional part of the log
$logFractionalPart = $log - $logIntegerPart;
// Calculate the value of 10 raised to the power of $logFractionalPart
$value = pow(10, $logFractionalPart);
// Round $value to specified number of significant figures
$value = round($value, $numberOfSigFigs - 1);
// Return the correct value
return $value * pow(10, $logIntegerPart);
}
}
While the functions here worked, I needed significant digits for very small numbers (comparing low-value cryptocurrency to bitcoin).
The answer at Format number to N significant digits in PHP worked, somewhat, though very small numbers are displayed by PHP in scientific notation, which makes them hard for some people to read.
I tried using number_format, though that needs a specific number of digits after the decimal, which broke the 'significant' part of the number (if a set number is entered) and sometimes returned 0 (for numbers smaller than the set number).
The solution was to modify the function to identify really small numbers and then use number_format on them - taking the number of scientific notation digits as the number of digits for number_format:
function roundRate($rate, $digits)
{
$mod = pow(10, intval(round(log10($rate))));
$mod = $mod / pow(10, $digits);
$answer = ((int)($rate / $mod)) * $mod;
$small = strstr($answer,"-");
if($small)
{
$answer = number_format($answer,str_replace("-","",$small));
}
return $answer;
}
This function retains the significant digits as well as presents the numbers in easy-to-read format for everyone. (I know, it is not the best for scientific people nor even the most consistently length 'pretty' looking numbers, but it is overall the best solution for what we needed.)

PHP convert decimal into fraction and back?

I want the user to be able to type in a fraction like:
1/2
2 1/4
3
And convert it into its corresponding decimal, to be saved in MySQL, that way I can order by it and do other comparisons to it.
But I need to be able to convert the decimal back to a fraction when showing to the user
so basically I need a function that will convert fraction string to decimal:
fraction_to_decimal("2 1/4");// return 2.25
and a function that can convert a decimal to a faction string:
decimal_to_fraction(.5); // return "1/2"
How can I do this?
Sometimes you need to find a way to do it and rounding is acceptable. So if you decide what range of rounding works out for you you can build a function like this. To convert a decimal into the fraction that it most closely matches. You can extend the accuracy by adding more denominators to be tested.
function decToFraction($float) {
// 1/2, 1/4, 1/8, 1/16, 1/3 ,2/3, 3/4, 3/8, 5/8, 7/8, 3/16, 5/16, 7/16,
// 9/16, 11/16, 13/16, 15/16
$whole = floor ( $float );
$decimal = $float - $whole;
$leastCommonDenom = 48; // 16 * 3;
$denominators = array (2, 3, 4, 8, 16, 24, 48 );
$roundedDecimal = round ( $decimal * $leastCommonDenom ) / $leastCommonDenom;
if ($roundedDecimal == 0)
return $whole;
if ($roundedDecimal == 1)
return $whole + 1;
foreach ( $denominators as $d ) {
if ($roundedDecimal * $d == floor ( $roundedDecimal * $d )) {
$denom = $d;
break;
}
}
return ($whole == 0 ? '' : $whole) . " " . ($roundedDecimal * $denom) . "/" . $denom;
}
I think I'd store the string representation too, as, once you run the math, you're not getting it back!
And, here's a quick-n-dirty compute function, no guarantees:
$input = '1 1/2';
$fraction = array('whole' => 0);
preg_match('/^((?P<whole>\d+)(?=\s))?(\s*)?(?P<numerator>\d+)\/(?P<denominator>\d+)$/', $input, $fraction);
$result = $fraction['whole'] + $fraction['numerator']/$fraction['denominator'];
print_r($result);die;
Oh, for completeness, add a check to make sure $fraction['denominator'] != 0.
To can use PEAR's Math_Fraction class for some of your needs
<?php
include "Math/Fraction.php";
$fr = new Math_Fraction(1,2);
// print as a string
// output: 1/2
echo $fr->toString();
// print as float
// output: 0.5
echo $fr->toFloat();
?>
Here is a solution that first determines a valid fraction (although not necessarily the simplest fraction). So 0.05 -> 5/100. It then determines the greatest common divisor of the numerator and denominator to reduce it down to the simplest fraction, 1/20.
function decimal_to_fraction($fraction) {
$base = floor($fraction);
$fraction -= $base;
if( $fraction == 0 ) return $base;
list($ignore, $numerator) = preg_split('/\./', $fraction, 2);
$denominator = pow(10, strlen($numerator));
$gcd = gcd($numerator, $denominator);
$fraction = ($numerator / $gcd) . '/' . ($denominator / $gcd);
if( $base > 0 ) {
return $base . ' ' . $fraction;
} else {
return $fraction;
}
}
# Borrowed from: http://www.php.net/manual/en/function.gmp-gcd.php#69189
function gcd($a,$b) {
return ($a % $b) ? gcd($b,$a % $b) : $b;
}
This includes a pure PHP implementation of the gcd although if you are sure the gmp module is installed you could use the one that comes with gcd.
As many others have noted you need to use rational numbers. So if you convert 1/7 to a decimal then try to convert it back to a decimal you will be out of luck because the precision lost will prevent it from getting back to 1/7. For my purposes this is acceptable since all the numbers I am dealing with (standard measurements) are rational numbers anyway.
Buddies, can this help?
[]s
function toFraction($number) {
if (!is_int($number)) {
$number = floatval($number);
$denominator = round(1 / $number);
return "1/{$denominator}";
}
else {
return $number;
}
}
Little improvement on above, but keepin it simple.
function dec2frac($f) {
$base = floor($f);
if ($base) {
$out = $base . ' ';
$f = $f - $base;
}
if ($f != 0) {
$d = 1;
while (fmod($f, 1) != 0.0) {
$f *= 2;
$d *= 2;
}
$n = sprintf('%.0f', $f);
$d = sprintf('%.0f', $d);
$out .= $n . '/' . $d;
}
return $out;
}
An approach would be to retrieve the decimal value and multiply it by 2, 3, 4 and so on until you get an integer number.
However, I'd stick with the answer given by Derek. Guess what happens when a user inserts n/(n+1) with n high. Such an algorithm would have to scan all the numbers up to n+1.
Not to mention it is likely you'll end up with approximation problems.
You'll have to face a serious problem, because floats are not precise enough.
When you'll have to deal with 1.3333, PHP will make an estimate of this value... So you will never be able to convert it to 1 1/3.
It seems to be simple to overcome, but if you want your program to differentiate 1/7901 (~ 1,2656625743576762435134793064169e-4) with 1/7907 (~
1,2647021626406981155937776653598e-4) precisely... this will be a real hell !!
IMHO, if you want to deal with maths, you should rely on an external library... or try to make PHP communicate with Matlab.
If you want to know more, i suggest you dig in floating point problems... Starting with wikipedia.
A variation of Jir's approach could actually work if only a limited amount of denominators are used : multiply everything by the least common denominators (and round the result to discard any remaining decimals due to approximation).
I.e.: if you only have to deal with halfs, thrids and quarters, just multiply everything by 12.
And also if you know the common denominator, this should greatly reduce the search speed by knowing exactly which numbers to search instead of searching all n+1 possible.
If you have to deal with lots of unusual fractions, like 1/7, 1/13, etc. well, stick to Derek's solution and store the original value too.
The fraction to decimal is quite straightforward and there are lots of solutions. I'd go with trimming the string, replacing spaces with '+', and anything other than space,/,. or digits with '' then running it through 'eval'.
The decimal to fraction is virtually impossible to do correctly - not least because your decimal fraction would probably have to be converted to binary first - at which point you loose a lot of precision. As an academic exercise.....If you can live with the difference between 20976/41953 and 1/2 then you could try a fuzzy match for a predefined number of fractions:
(there's probably a neater way of implementing the same algorithm - but I'll leave that as an exercise for the reader).
define('DECIMAL_DIGITS',5);
function decimal_2_frac($inp_decimal)
{
static $fracs;
if (!is_array($fracs)) {
init_fracs($fracs);
}
$int_part=(integer)$inp_decimal;
$inp_decimal=$inp_decimal-$int_part;
$candidate='';
$distance=10;
foreach ($fracs as $decimal=>$frac) {
if (abs($decimal-$inp_decimal)<$distance) {
$candidate=$frac;
$distance=abs($decimal-$inp_decimal);
}
if (abs($decimal-$inp_decimal)>$distance) {
break;
}
}
return $int_part . ' ' . $candidate;
}
function init_fracs(&$fracs)
{
$fracs=array();
for ($x=2;$x<(5*DECIMAL_DIGITS);$x++) {
// there's probably a beter way to calculate the loop limit
for ($y=1; $y<$x; $y++) {
$decimal=round($y/$x,DECIMAL_DIGITS);
$frac="$x/$y";
if (!array_key_exists($decimal,$fracs)) {
$fracs[$decimal]=$frac;
}
}
}
}
But personally, I'd just store the original representation in a seperate field in the database.
function dec2frac($f)
{
$d = 1
while (fmod($f, 1) != 0.0) {
$f *= 2;
$d *= 2;
}
$n = sprintf('%.0f', $f);
$d = sprintf('%.0f', $d);
return array($n, $d);
}
Then $f == $n / $d
For example:
print_r(dec2frac(3.1415926));
Outputs:
Array
(
[0] => 3537118815677477 // $n
[1] => 1125899906842624 // $d
)
I made a blog post with a couple solutions for this, the most recent approach I took is:
http://www.carlosabundis.com/2014/03/25/converting-decimals-to-fractions-with-php-v2/
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;
}
Just adding a bit more logic to Derek's accepted answer - check for "division by zero" and whole number input check.
function fractionToDec($input) {
if (strpos($input, '/') === FALSE) {
$result = $input;
} else {
$fraction = array('whole' => 0);
preg_match('/^((?P<whole>\d+)(?=\s))?(\s*)?(?P<numerator>\d+)\/(?P<denominator>\d+)$/', $input, $fraction);
$result = $fraction['whole'];
if ($fraction['denominator'] > 0)
$result += $fraction['numerator'] / $fraction['denominator'];
}
return $result;
}
function frac2dec($fraction) {
list($whole, $fractional) = explode(' ', $fraction);
$type = empty($fractional) ? 'improper' : 'mixed';
list($numerator, $denominator) = explode('/', $type == 'improper' ? $whole : $fractional);
$decimal = $numerator / ( 0 == $denominator ? 1 : $denominator );
return $type == 'improper' ? $decimal : $whole + $decimal;
}
Use a 3rd party library, for example:
https://packagist.org/packages/phospr/fraction
Usage:
$fraction = Fraction::fromFloat(1.5);
echo "Fraction is: " . $fraction->getNumerator() . '/' . $fraction->getDenominator();
echo "Float is: " . $fraction->toFloat();
I usually do a quick search on https://packagist.org to see if something already exists to solve what I'm trying to do, if so then I can take advantage of the many hours that the community have already put into solving the problem (this will be much much more time than I'll be able to dedicate to it) and it will also be more likely to be bug free, having been battle tested by others and maybe even have a test suite covering it.
Saves time and results in higher quality.

Categories