PHP Number Format - Aligning Numbers with Brackets - php

I'm using the following function to turn my numbers into 2 decimals with negatives in parenthesis.This almost works
However as I have them right aligned they don't quite line up as i'd like.
The ) sits above the 3. It would be better if the 4 and 3 aligned above each other.
(11,870.74)
2,806.33
Is any of this possible?
function myformat($nr)
{
$nr = number_format($nr, 2);
return $nr[0] == '-' ? "(" . substr($nr, 1) . ")" : $nr;
}

Add a space at the end of the positive number, to match the close parenthesis:
function myformat($nr)
{
$nr = number_format($nr, 2);
return $nr[0] == '-' ? "(" . substr($nr, 1) . ")" : $nr . ' ';
}
I assume you're using printf() in the caller to right-align the results.

Related

php dechex with dark colors only

I am using php's dechex function to generate random colors as per requirements.Here is my working code.
dechex(rand(0x000000, 0xFFFFFF));
Howerver, I want to use dark colors only. I have found this code so far which generated only light colors thanks for this and this article.
However, I am yet to find a proper solution to generate only dark colors. I have tried several things like below.
'#' . substr(str_shuffle('AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899'), 0, 6);
And
'#' . substr(str_shuffle('ABCDEF0123456789'), 0, 6);
But these, sometimes generating light colors randomly.
Edit:
I would like to have a solution with hex and rgb.
How Can I achieve this ?
Here how to get dark color for both Hex and RGB
$hexMin = 0;
$hexMax = 9;
$rgbMin = 0;
$rgbMax = 153; // Hex 99 = 153 Decimal
$hex = '#' . mt_rand($hexMin,$hexMax) . mt_rand($hexMin, $hexMax) . mt_rand($hexMin, $hexMax) . mt_rand($hexMin,$hexMax) . mt_rand($hexMin, $hexMax) . mt_rand($hexMin, $hexMax);
$rgb = 'rgb(' . mt_rand($rgbMin,$rgbMax). ',' . mt_rand($rgbMin,$rgbMax). ',' . mt_rand($rgbMin,$rgbMax). ')';
Put your HEX to contain only dark colors by limiting max value:
$max = 9;
'#' . mt_rand(0. $max) . mt_rand(0. $max) . mt_rand(0. $max);
generate a random color :
function darker_color($rgb, $darker=2) {
$hash = (strpos($rgb, '#') !== false) ? '#' : '';
$rgb = (strlen($rgb) == 7) ? str_replace('#', '', $rgb) : ((strlen($rgb) == 6) ? $rgb : false);
if(strlen($rgb) != 6) return $hash.'000000';
$darker = ($darker > 1) ? $darker : 1;
list($R16,$G16,$B16) = str_split($rgb,2);
$R = sprintf("%02X", floor(hexdec($R16)/$darker));
$G = sprintf("%02X", floor(hexdec($G16)/$darker));
$B = sprintf("%02X", floor(hexdec($B16)/$darker));
return $hash.$R.$G.$B;
}
$color = '#'.dechex(rand(0x000000, 0xFFFFFF));
$dark = darker_color($color);
echo "$color => $dark";
Even if a random generated color is dark , the function pick up a darker color . normaly it goes to black color .
The main thing you seem to want is to ensure that each pair of hex digits is below a certain level once you've generated a random number. As rand() will generate any value up to the limit, my approach is to keep your original limit of 0xffffff but once the number has been generated, apply a bitwise and (&) to clear the high bits for each byte...
echo '#'.dechex(rand(0x000000, 0xFFFFFF) & 0x3f3f3f);
You can tweak the 0x3f3f3f to a limit which you want to set to limit the maximum value.

Modify decimal point and thousands separator without changing the number of decimals

I'm new to php and I'm trying to use number_format :
number_format ( float $number , int $decimals = 0 , string $dec_point = "." , string $thousands_sep = "," )
As in the title, my goal is to modify decimal point and thousands separator without changing the number of decimals as below:
$Num=123456.789;
$Num2=number_format ($Num, [decimals as in $Num], ",", "'" );
My result should be:
$Num2="123'456,789";
Edit
I need a code for an unknown number of decimals
You can use NumberFormatter.
You will still need to specify a certain amount of fraction digits, but you can just use a high enough value and be fine. It's not like the number of digits is really arbitrary. It's tied to your precision ini setting.
$formatter = new NumberFormatter("en_US", NumberFormatter::DECIMAL);
$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 42);
$formatter->setSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, "'");
$formatter->setSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL, ",");
echo $formatter->format(123456.7891234); // 123'456,7891234
Demo https://3v4l.org/TCAIA
You can do it such a way (firstly take a look to #Gordon answer – it's much more better):
<?php
function extendedNumberFormat($num, $decimalSeparator, $thousandSeparator) {
$asStr = strval($num);
$exploded = explode('.', $asStr);
$int = $exploded[0];
$decimal = isset($exploded[1]) ? $exploded[1] : null;
$result = number_format($int, 0, ".", $thousandSeparator);
if ($decimal !== null) {
$result .= $decimalSeparator . $decimal;
}
return $result;
}
echo extendedNumberFormat(123456.789, ',', "'") . "\n";
echo extendedNumberFormat(123456.7891, ',', "'") . "\n";
echo extendedNumberFormat(123456, ',', "'") . "\n";
//123'456,789
//123'456,7891
//123'456

How to get the number series of two bits set, of an 16bit int?

(Working on a search algorithm) I want to iterate over possible matches with two bits set in a 16bit word. Seems like a silly problem with a currently overly-complex solution.
Iteration should return (decimal) 3,5,6,9,10,12,17...
What's the proper word for the problem? Bit-mask-looping?
Any clever function for this?
Current code - now updated:
(As it stands, i guess there's no easier way around this.)
<?php
function biterate($numBits=8, $setBits=2, $maxval=null) {
//init
if(is_null($maxval)) $maxval = (pow(2,$setBits)-1) * pow(2,$numBits - $setBits);
$err = 0;
header('content-type:text/plain');
echo '-- ' . $setBits . ' of ' . $numBits . " --\r\n";
$result = str_pad('', $numBits - $setBits, '0') . str_pad('', $setBits, '1');
do {
$err++;
if($err > 200) die('bad code');
//echo and calc next val.
echo $result . ' : ' . bindec($result) . "\r\n";
//count set bits and search for '01' to be replaced with '10'. From LSB.
$bitDivend = '';
$hit = false;
for($i=$numBits;$i>0;$i--) {
if(substr($result,$i-2,2) == '01') {
$hit = true;
//do the replacement and replace the lower part with bitDivend.
$result = substr($result, 0, $i-2) . '10';
$result .= str_pad('',$numBits - $i - strlen($bitDivend),'0');
$result .= $bitDivend;
//exit loop
$i = 0;
}
if($result[$i-1] == '1') $bitDivend .= '1';
}
} while($hit && bindec($result) <= $maxval);
}
biterate(8,2);
biterate(8,7);
biterate();
If you just want all the 16 bit ints with 2 bits set, the following code should do it:
<?php
for($i=1;$i<16;$i++)
{
for($j=0;$j<$i;$j++)
{
echo (1<<$i)|(1<<$j) , "\r\n";
}
}
?>
If you look at the bit patterns of the numbers you can see how it works:
11 3
101 5
110 6
1001 9
1010 10
1100 12
10001 17
10010 18
10100 20
11000 24
etc. You just move the most significant bit one place to the left (another power of 2) for each iteration of the outer loop, and inside the inner loop you iterate from the least significant bit (1) to 1 place to the right of the most significant bit.
If you wanted to generalise this to support an arbitrary number of bits and places, you could extend the above algorithm using recursion:
<?php
function biterate_recursive($numBits=8, $setBits=2, $initialValue=0, $maxval=null) {
for($i=$setBits-1;$i<$numBits;$i++)
{
if(!is_null($maxval) && ($initialValue|(1<<$i)) > $maxval)
break;
if($setBits==1)
echo $initialValue|(1<<$i) , "\r\n";
else
biterate_recursive($i, $setBits-1, $initialValue|(1<<$i), $maxval);
}
}
biterate_recursive(16, 2);
?>
You can also think of the problem as just choosing combinations i.e. C(16,2) choosing 2 numbers a,b from the set 0-15, and then calculating (1<<a)|(1<<b). However you have to be careful about your choice of combination algorithm if you want to get the numbers in order.

How can i loop this process more effectively

I have written a little script to automate some calculations for me. It is pretty simple.
1*3=3
2*3=6
3*3=9 and so on. When the answer(product) is more than one digit long I want it to add the digits of the answer.
3*4=12 || 1+2=3.
I want it to automatically add the answer if it is more than one digit no matter how many times adding the answer arrives larger than a single digit.
as in when you reach 13*3=39 || 3+9=12 || 1+2=3
Currently my code does not loop, and i cannot figure out how to make it loop here.
http://screencast.com/t/MdpQ9XEz
Also, it is not adding up more than 2 digit answers see 34*3=102. any help here to allow it infinity addition would be great.
As each line is produced the answers get larger, so it should add as many digits there are in the answer.
here is my code:
$i = 1; //Start with one
function count_digit($number) {
return strlen((string) $number);
};
while($i < 500){
$product = $i * 3; //Multiply set
$number_of_digits = count_digit($product); //calls function to count digits of $sum
if($number_of_digits > 1){ //if $sum has more than one digit add the digits together
$addproduct = strval($product);//seperates the digits of $sum
$ii = 0;
while($ii <= $number_of_digits -1){
$io = $ii + 1;
if($io < $number_of_digits){
$one = intval($addproduct[$ii]);
$two = intval($addproduct[$io]);
$sum = $one + $two;
print($i . ' * 3 = ' .$product. ' || ' .$one. ' + ' .$two. ' = ' .$sum. '<br>');
};$ii++;
};
}else{
Print ($i . ' * 3 = ' .$product.'<br>'); //Print Set
};
$i++; //add one
}
For a start, you might replace the $i=1, while ..., and $i++ into one statement: for ($i=0; $i<500; $i++) {.... - see http://nz1.php.net/manual/en/control-structures.for.php for more information about for loops. It comes out to effectively the same code, but keeps the three parts (initialisation, test, increment counter) together; it makes it clear that they are related, and quicker to understand.
Next I would replace conversion of the number to a string, seeing if the length of the string is greater than one, etc.... with:
while ($product>10) {
$out=0;
while ($product) {
$out+=$product%10;
$product=(integer)($product/10);
}
$product=$out;
}
Note that at no time am I treating a number as a string - I avoid that wherever possible.
In case you are not familiar with it, $something+=$somethingelse is the same as $something=$sometime+$somethingelse, just a shorthand. $out is the running total, and each time around the inner loop (while $product), $out is increased by the rightmost digit (the ones column): $out+=$product%10 - see http://nz2.php.net/operators.arithmetic for more info, then $product is divided by 10 and converted to an integer, so 12 becomes 1.2, then 1, dropping the right-most digit.
Each time the inner loop is complete (all the digits of $product are used up, and $product is 0), the result (in $out) is copied to $product, and then you get back to the outer loop (to see if the sum of all these digits is now less than 10).
Also important is exactly where in each loop you print what. The first part, with the multiplication, is immediately in the '500' loop; the '||' happens once for each time '$product' is reduced to '$out'; the adding of the digits happens inside the innermost loop, with '+' either BEFORE each digit except the first, or AFTER each digit except the last. Since 'all except the last' is easier to calculate ($product>=10, watch those edge cases!), I chose that one.
Also note that, since I'm adding the digits from the right to the left, rather than left-to-right, the addition is reversed. I do not know if that will be an issue. Always consider if reversing the order will save you a lot of work. Obviously, if they NEED to be done in a particular order, then that might be a problem.
The result is:
for ($i=0; $i<500; $i++) {
$product = $i * 3; //Multiply set
print ($i . ' * 3 = ' .$product);
while ($product>10) {
print ' || ';
$out=0;
while ($product>0) {
print ($product%10);
if ($product>=10) {
print " + ";
}
$out+=$product%10;
$product=(integer)($product/10);
}
$product=$out;
print(' = ' .$product);
}
print "<br>";
};
I've decided to add this as a separate answer, because it uses a different approach to answer your question: the least amount of changes to fix the problem, rather than rewriting the code in an easy-to-read way.
There are two problems with your code, which require two separate fixes.
Problem 1: Your code does not add 3 digit (or more) numbers correctly.
If you look carefully at your code, you will notice that you are adding pairs of numbers ($one and $two); each time you add a pair of numbers, you print it out. This means that for the number 102, you are adding 1 and 0, printing out the results, then adding 0 and 2 and printing it out. Look carefully at your results, and you will see that 102 appears twice!
One way to fix this is to use $three and $four (4 digits is enough for 500*3). This is not good programming, because if you later need 5 digits, you will need to and $five, and so forth.
The way to program this is to start with a $sum of zero, then go through each digit, and add it to the sum, thusly:
$ii = 0;
$sum = 0;
while($ii <= $number_of_digits - 1){
$one = intval($addproduct[$ii]);
$sum = $sum + $one;
$ii++;
}
print($i . ' * 3 = ' .$product. ' || ' . $sum . '<br>');
};
The inner if disappears, of course, since it relates to $io, which we are no longer using.
Of course, now you lose your ability to print the individual digits as you are adding them up. If you want those in, and since we don't know in advance how many there are, you would have to keep a record of them. A string would be suitable for that. Here is how I would do it:
$ii = 0;
$sum = 0;
$maths = "";
while($ii <= $number_of_digits-1){
$one = intval($addproduct[$ii]);
if ($maths=="") {
$maths=$one;
} else {
$maths=$maths . " + " .$one;
}
$sum = $sum + $one;
$ii++;
}
print($i . ' * 3 = ' .$product. ' || ' . $maths . " = " . $sum . '<br>');
};
Note the lines with $math in them; there's one at the top, setting it to an empty string. Then, once we've decided on what number we're adding, we add this to $maths. The first time round is a special case, since we don't want "+" before our first digit, so we make an exception - if $maths is empty, we set it to $one; later times around the loop, it's not empty, so we add " + " . $one;
Problem 2: if the result of the addition is more than 1 digit long, go around again. And again, as many times as required.
At this point I would suggest a little refactoring: I would break the print statement into several parts. First the multiplication - that can easily be moved to the top, immediately after the actual multiplication. Printing the <br> can go at the end, immediately before the $i++. This also means you no longer need the else clause - it's already done. This only leaves the ' || ' . $maths . " = " . $sum. This is going to have to happen every time you go through the adding.
Now, replace your if($number_of_digits... with a while($number_of_digits...; this means it goes through as many times as is needed, if it's zero or 100. This does mean that you're going to have to update $product at the end of your loop, with $product = $sum; - put this immediately after the print statement. You will also need to update $number_of_digits; copy the line from the top to the end of the loop.
If you've been following along, you should have:
$i = 1; //Start with one
function count_digit($number) {
return strlen((string) $number);
};
while($i < 500){
$product = $i * 3; //Multiply set
print($i . ' * 3 = ' .$product); // Print basic multiplication
$number_of_digits = count_digit($product); //calls function to count digits of $sum
while ($number_of_digits > 1){ //if $sum has more than one digit add the digits together
$addproduct = strval($product);//seperates the digits of $sum
$ii = 0;
$sum = 0;
$maths = "";
while($ii <= $number_of_digits-1){
$one = intval($addproduct[$ii]);
if ($maths=="") {
$maths=$one;
} else {
$maths=$maths . " + " .$one;
}
$sum = $sum + $one;
$ii++;
}
print(" || " . $maths . " = " . $sum ); // print one lot of adding
$product=$sum;
$number_of_digits = count_digit($product); //calls function to count digits of $sum
};
Print ("<br>"); //go to next line
$i++; //add one
}

Can I use the $string number_format line to superscript my decimals?

I would like to make the decimals in the following string display as superscript:
$string .= number_format(round($value, (int)$decimal_place), (int)$decimal_place, $decimal_point, $thousand_point);
I'm not very smart but I have been trying since yesterday using different methods I've found searching stack overflow. Stuff like ."<sup> or just "<sup>" and also .'<sup>' and so many other combinations, but nothing works. I either get an error or the price disappears due to the error I introduce into the code because as I said I'm not the sharpest tool in the shed.
Please check out the code I have below, this will format your string, and then use regular expressions to superscript the decimal
<?
function superscript_value($value, $prefix = '$') {
$decimal_place = 2;
$decimal_point = '.';
$thousand_point = ',';
if(round($value, 0) == $value)
return $prefix . $value;
else
return $prefix . preg_replace("/\.(\d*)/", "<sup>.$1</sup>", number_format($value, (int)$decimal_place, $decimal_point, $thousand_point));
}
echo superscript_value(123456.789, '$') . "\n";
// $123,456<sup>.79</sup>
echo superscript_value(10.00, '$') . "\n";
// $10
$123,456.79
$10
You should use HTML formatting for that:
$i = 42;
$string .= "<sup>".$i."</sup>";
It will produce something like 42.

Categories