Japanese currency formatting for readability - php

I'd like to format Japanese currency into the standard "quickly readable" format.
Basically, all amounts over 10,000 yen are written using the character "万" (pronounced "man").
More on "万"
http://www.romajidesu.com/kanji/%E4%B8%87
So, 1,000,000 yen would simply be 100万 or "one hundred man". That's roughly $1,000 USD.
Virtually no one in Japan would ever say "one million yen". The currency is always broken into 10,000 yen bundles.
Consequently, when you buy a car, the sticker on the windshield says (e.g.) "140万"
So, I'd like to display that format. However, number_format, I believe, does not allow for defining the separation at 10,000, and money_format is likewise unhelpful.
Any thoughts on a best practice method for accomplishing this?
In summary:
10,000 yen should read 1万
100,000 yen should read 10万
1,000,000 yen should read 100万

I have ever written that in my WordPress plugin,
/**
* convert number expressions to value
*
* #assert ("34000") == "3万4000円"
* #assert ("123456.789") == "12万3457円"
* #assert ("1234567890") == "12億3456万7890円"
* #assert ("92610000000000") == "92兆6100億円"
*/
public static function formatInJapanese($value) {
$isApproximate = false;
$formatted = '';
if ($value > 1000000000000) {
if ($value % 1000000000000 !== 0) {
$isApproximate = true;
}
$unitValue = floor($value / 1000000000000);
$formatted .= $unitValue . '兆';
$value -= $unitValue * 1000000000000;
}
if ($value > 100000000) {
if ($value % 100000000 !== 0
&& !$isApproximate) {
$isApproximate = true;
}
$unitValue = floor($value / 100000000);
$formatted .= $unitValue . '億';
$value -= $unitValue * 100000000;
}
if ($value > 10000) {
if ($value % 10000 !== 0
&& !$isApproximate) {
$isApproximate = true;
}
$unitValue = floor($value / 10000);
$formatted .= $unitValue . '万';
$value -= $unitValue * 10000;
}
if ($value != 0) {
$formatted .= round($value);
}
return $formatted . '円';
}
It only works with man, oku and cho.
Quick search gives me that Ruby gem number_to_yen doing similar.

The solution I came up with is similar to the above.
function format_yen_for_display($yenAmount)
{
/*
Converts Japanese currency to easily readable local format
10,000 yen should read 1万
100,000 yen should read 10万
1,000,000 yen should read 100万
1,259,000 yen should read 125万 9,000円
*/
if($yenAmount > 10000)
{
//amount over 1万
$manYen = floor($yenAmount/10000);
//amount under 1万
$remainderYen = ($yenAmount - ($manYen * 10000));
//concat
$returnNum = "<span class=\"ylarge\">" . $manYen . "万</span>";
//if remainder is more than zero, show it
if($remainderYen > 0)
{
//format remainder with thousands separator
$remainderYen = number_format($remainderYen);
$returnNum .= "<span class=\"ysmall\">" . $remainderYen ."円</span>";
}
}
else
{
$returnNum = "<span class=\"ylarge\">" . $yenAmount . "円</span>";
}
return $returnNum;
}

Related

If a number is too large use an abbreviation

I am creating a social site. And I want to show people things like their total amount of likes, followers and people they are following. The way it is now, it shows the total amount of likes, followers and following as a whole number and if it's too long it will go over other words on the page.
So how do I use abbreviations like: K(for thousands), m(millions) etc ? This is what I have now.
$stmt = $con->prepare('SELECT name, username, num_likes, profile_pic FROM users WHERE user_closed = "0"
ORDER BY num_likes DESC LIMIT 100');
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($name, $username, $num_likes, $profile_pic);
function convert($num_likes)
{
$num_likes = $number / 1000;
return $num_likes . 'k';
}
This is how I show the result: <p> Total Likes: " . $num_likes ."</p>
I tried the following:
PHP Count round thousand to a K style count like facebook Share . . . Twitter Button ect
Shorten long numbers to K/M/B?
PHP Count round thousand to a K style count Facebook Share
First of all, your function:
function convert($num_likes)
{
$num_likes = $number / 1000;
return $num_likes . 'k';
}
will not work as expected, because it converts to the opposite way :) Here is updated version:
function convert($num_likes)
{
$number = $num_likes / 1000;
return $number . 'k';
}
Second point. You should use the function somewhere... for example your line (actually only a part of it):
<p> Total Likes: " . $num_likes ."</p>
must be:
<p> Total Likes: " . convert($num_likes) ."</p>
And finally, using this answer we can modify convert function to this:
function convert($n) {
if ($n < 1000) {
$n_format = number_format($n);
} else if ($n < 1000000) {
// Anything less than a million
$n_format = number_format($n / 1000, 3) . 'k';
} else if ($n < 1000000000) {
// Anything less than a billion
$n_format = number_format($n / 1000000, 3) . 'M';
} else {
// At least a billion
$n_format = number_format($n / 1000000000, 3) . 'B';
}
return $n_format;
}
Now we can convert all numbers up to billions.
Playground: click.
Perhaps like this,
Use round() if you don't want large fractions.
<?php
function convert(int $number)
{
if ($number >= 1E9) {
return round($number / 1E9, 2).'b';
} else if ($number >= 1E6) {
return round($number / 1E6, 2).'m';
} else if ($number >= 1E3) {
return round($number / 1E3, 2).'k';
}
return $number;
}
echo convert(1000000000).PHP_EOL; // 1b
echo convert(1000000).PHP_EOL; // 1m
echo convert(1200).PHP_EOL; // 1.2k
echo convert(1234).PHP_EOL; // 1.23k
echo convert(100).PHP_EOL; // 100
https://3v4l.org/cc54H

Express Amount In Words with Decimal Value

Im using the number formatter class in php and it needs to format it in currency and also in words, the problem is the value that it needs to be formatted has decimal value and it gives me the value two thousand nine hundred three point zero four and it shoud be two thousand nine hundred three and four cents, if the value has decimal it gives me a literal word point here is my code
$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);
$formated = $f->format(2903.04);
please help me thanks
There's no defined spell-out formatter for currency, and while you could probably write one I think that that might be a bit of overkill.
What you could do instead is split the dollars as cents into separate values, spell those out, and combine them.
First and foremost though, you do not want to store or compute currencies with floating point representations. I was going to save this point for last, but I couldn't even get through the initial steps before floating point errors crept in.
$v = 2903.04;
$d = (int)$v; // casting to int discards decimal portion
$c = (int)(($v - $d) * 100);
var_dump($v, $d, ($v - $d) * 100, $c);
Output:
float(2903.04)
int(2903)
float(3.9999999999964)
int(3)
Use something like moneyphp/money which stores monetary values as integer amounts of base currency units. [eg: $2903.04 == 290304] This avoids errors like the above, as well as messy kludges to do with rounding. Additionally, money libraries will implement safe mathematical operations to do operations like dividing $1.00 among 3 recipients without splitting or losing pennies.
Instead, let's write the code like:
$a = 290304; // full amount in cents
$c = $a % 100; // cent remainder
$d = ($a - $c) / 100; // dollars
$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);
var_dump(
$a, $d, $c,
sprintf("%s dollars and %s cents", $f->format($d), $f->format($c))
);
Output:
int(290304)
int(2903)
int(4)
string(54) "two thousand nine hundred three dollars and four cents"
Check my working converter : https://smctgroup.com/contracts/number.php
Input: 2903.04
Output : Two Thousand Nine Hundred Three Pesos and Four Centavos
You can change Pesos to Dollar
You can use this function:
function makewords($numval)
{
$moneystr = "";
$num_arr = explode(".", $numval);
$decnum = $num_arr[1];
// handle the millions
$milval = (integer)($numval / 1000000);
if($milval > 0)
{
$moneystr = getwords($milval) . " Million";
}
// handle the thousands
$workval = $numval - ($milval * 1000000); // get rid of millions
$thouval = (integer)($workval / 1000);
if($thouval > 0)
{
$workword = getwords($thouval);
if ($moneystr == "")
{
$moneystr = $workword . " Thousand";
}
else
{
$moneystr .= " " . $workword . " Thousand";
}
}
// handle all the rest of the dollars
$workval = $workval - ($thouval * 1000); // get rid of thousands
$tensval = (integer)($workval);
if ($moneystr == "")
{
if ($tensval > 0)
{
$moneystr = getwords($tensval);
}
else
{
$moneystr = "Zero";
}
}
else // non zero values in hundreds and up
{
$workword = getwords($tensval);
$moneystr .= " " . $workword;
}
// plural or singular 'dollar'
$workval = (integer)($numval);
if ($workval == 1)
{
$moneystr .= " Peso";
}
else
{
$moneystr .= " Pesos";
}
// //My cents
// if ($workint > 0) {
// $moneystr .= " and ";
// if ($workint < 20) {
// $moneystr .= $ones[$workint];
// } elseif ($workint < 100) {
// $moneystr .= $tens[substr($workint, 0, 1)];
// $moneystr .= " ".$ones[substr($workint, 1, 1)];
// }
// }
// do the pennies - use printf so that we get the
// same rounding as printf
$workstr = sprintf("%3.2f",$numval); // convert to a string
$intstr = substr($workstr,strlen - 2, 2);
$workint = (integer)($intstr);
if($decnum>0) {
$moneystr .= " and ";
if ($workint == 0)
{
$moneystr .= "Zero";
}
else
{
$moneystr .= getwords($decnum);
}
if ($workint == 1)
{
$moneystr .= " Centavo";
}
else
{
$moneystr .= " Centavos";
}
}
// done - let's get out of here!
return $moneystr;
}

PHP Money Format

Basically, I need a function to help me achieve this:
I have a raw integer, say 5000, which is an amount of money. It's not formatted in any way. I want to be able to convert 5000 into a string like "$5k".
If the amount was 1000000 (one million), the string would be "$1m".
If the amount was 1000000000 (one billion), the string would be "$1b";
I also need to round the number, so say the amount was 5555555, the string would be "$5.5m"
A simple way to do that id to create a format function like this :
function format($amount) {
if ($amount < 1000) {
return '$' . $amount;
} else if($amount < 1000000) {
$amount /= 1000;
return '$' . round($amount, 1) . 'k';
} else if($amount < 1000000000) {
$amount /= 1000000;
return '$' . round($amount, 1) . 'm';
} else {
$amount /= 1000000000;
return '$' . round($amount, 1) . 'b';
}
}
If you're running PHP on a system with strfmon capabilities, you can use the money_format method (windows don't support it).

Improve performance of php on local server

I have a XAMPP install, with pretty much the default config.
Performance isn't much of a problem in general as I use PHP mostly to run web pages and small web apps. Waiting a couple seconds for a page is not unusual.
However, I have recently taken up the problems from Project Euler and decided to do them in PHP.
Try as I may, I couldn't get my code to run in less than 1 minute 1 second (optimized down from almost 3 min) and I was getting pretty embarrassed, especially considering most posters on Pjt Euler reported times of 1-3 seconds. (#7, find the 10001th prime)
I ported my code to C#, and the same task completed in a blink. 0.4 seconds. Same algorithm, the only notable difference in the code is that I used a List in C# to replace the array I was using in PHP.
While I did expect C# to outperform php, this difference leads me to suspect a gross configuration problem, but I have no idea where to look.
What could be the cause of this poor performance?
Edit: Here is the code:
In PHP:
/*
* Project Euler #7:
* By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
* What is the 10001st prime number?
*/
ini_set('max_execution_time', 300);
echo "start time:" . date("i:s:u") . "<br />";
function isPrime($number, $prevPrimes)
{
foreach ($prevPrimes as $key =>$prime)
{
if ($prime == 1)
{
continue;
}
elseif ($number % $prime == 0)
{
return 0;
}
}
// If we get to here, $number is prime
return $number;
}
$primes = array();
$i = 0;
$nbPrimes = 0;
while ($nbPrimes <10001)
{
$i++;
if ($i % 2 != 0)
{
$result = isPrime($i, $primes);
if ($result != 0)
{
$primes[] = $i;
$nbPrimes++;
}
}
}
echo "#$nbPrimes: $result<br>";
echo "End time:" . date("i:s:u") . "<br />";
In C#:
public static void RunSnippet()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<int> primes = new List<int>();
int i = 0;
int nbPrimes = 0;
int result =0;
while (nbPrimes <10001)
{
i++;
if (i % 2 != 0)
{
result = isPrime(i, primes);
if (result != 0)
{
primes.Add(i);
nbPrimes++;
}
}
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}",
stopwatch.Elapsed);
Console.WriteLine ("#" + nbPrimes + ": " + result.ToString());
}
public static int isPrime(int number, List<int> prevPrimes)
{
foreach (int prime in prevPrimes)
{
if (prime == 1)
{
continue;
}
else if (number % prime == 0)
{
return 0;
}
}
// If we get to here, number is prime
return number;
}
"Use the force ..." of math! Just throwing some code pointless. Here are just a few points that can boost the performance.
why you are using array to match the number against?
the foreach function is thus ineffective - the cycle should end at floor(sqrt(number))
example: sqrt(64) = 8 -> all prime dividers will be from 1 to 8. The others will be product of them( 32 = 4 x 8 = 2x2x2x2x2 )
use formulas to jump to the next possibly prime number
math:
numbers divisable by 2 - 2, 4, 6, 8, 10, 12 -> 2k+1 = 2x1+1 = 3, 5, .....
numbers divisable by 3 - 3, 6, 9, 12 -> we already have 6 and 12, so 3, 9, 15, 21 -> 3(2k-1) = 3(2x1-1) = 3, 9, ...
here is some pseudo code from hk admin at project euler
isPrime ( number )
{
if ( number == 1 ) return false
elseif ( number < 4 ) return true
elseif ( number % 2 == 0 ) return false
elseif ( number < 9 ) return true
elseif ( number % 3 == 0 ) return false
else
r = floor ( sqrt ( number ) )
f = 5
while ( f <= r )
{
if ( number % f == 0 ) return false
if ( number % ( f + 2 ) == 0 ) return false
f = f + 6
}
return true
}
PS
About the difference in the speed of the execution - PHP is interpreted language, to view the result in browser you have 3 programs running - browser, server, php interpreter. You make a http request, the server calls php (and probably a bunch of other stuff, logging for example),php reads the script and executes it. There are much more steps than in C#.
In C# the compiled code is executed.
FINAL EDIT
Here is the PHP code from Bakudan's logic, which returns this result:
start time:44:25:000000
#10001: 104759
End time:44:26:000000
The Code:
<?php
echo "start time:" . date("i:s:u") . "\n";
function isPrime($number, &$primes)
{
if ($number === 1) return false;
elseif ($number %2 === 0) return false;
elseif ($number < 4) return true;
elseif ($number < 9) return true;
elseif ($number %3 === 0) return false;
else $r = floor(sqrt($number));
$f = 5;
while ($f <= $r) {
if ($number % $f ===0) return false;
if ($number % ($f+2) === 0) return false;
$f = $f + 6;
}
return true;
}
$primes = array();
$nbPrimes = $i = 0;
while ($nbPrimes < 10001)
{
$i++;
if (isPrime($i, $primes) !== false)
{
$primes[] = $i;
$nbPrimes++;
}
}
echo "#$nbPrimes: " . end($primes) . "\n";
echo "End time:" . date("i:s:u") . "\n";
Bakudan gave me the pseudo code, I Just translated and wrote it out for the OP's script above.
EDIT 2
I cleaned up the code a bit, didn't improve anything, may enhance "readability". But yea, I think this is the best you will get with PHP, which on an i7 without apache yields 5 seconds.
<?php
echo "start time:" . date("i:s:u") . "\n";
function isPrime($number, &$primes)
{
foreach($primes as $prime) {
if ($number % $prime === 0 && $prime > 1)
return false;
}
}
$primes = array();
$nbPrimes = $i = 1;
while ($nbPrimes <= 10001)
{
if ($i % 2 !== 0 && isPrime($i, $primes) !== false)
{
$primes[] = $i;
$nbPrimes++;
}
$i++;
}
echo "#$nbPrimes: " . end($primes) . "\n";
echo "End time:" . date("i:s:u") . "\n";
EDIT
Knocked another second off by moving the $prime === 1 to be after the $number % $prime check in the same if statement.
start time:29:40:000000
#10001: 104743
End time:29:45:000000
Taking Hannes suggestion of strict checking and passing the array as reference plus adding a few tweaks of my own (modifying the array inside the function):
ini_set('max_execution_time', 300);
echo "start time:" . date("i:s:u") . "\n";
function isPrime($number, &$prevPrimes)
{
foreach ($prevPrimes as $prime) {
if ($number % $prime === 0 && $prime !== 1)
{
return false;
}
}
// If we get to here, $number is prime
$prevPrimes[] = $number;
return $number;
}
$primes = array();
$i = 0;
$nbPrimes = 0;
while ($nbPrimes < 10001)
{
$i++;
if ($i % 2 !== 0)
{
$result = isPrime($i, $primes);
if ($result !== 0)
{
$nbPrimes++;
}
}
}
echo "#$nbPrimes: $result\n";
echo "End time:" . date("i:s:u") . "\n";
Which ended up being:
start time:52:08:000000
#10001: 104743
End time:52:15:000000
VS your code:
start time:50:44:000000
#10001: 104743
End time:51:17:000000
A good improvement there, but nothing like C#, just goes to show the power of a compiled language :)
While I did expect C# to outperform
php, this difference leads me to
suspect a gross configuration problem,
but I have no idea where to look.
Firing the PHP engine creates a little overhead for the webserver. The way PHP is loaded (e.g. loaded as a module on server startup or loaded on demand for every .php request) determines how much overhead is involved. Then on windows there are two variants of PHP available: thread-safe and non thread-safe, the latter one is claimed to be faster.
If its a XAMPP configuration problem, I think you can isolate it by running the test 3 times on your webserver and note down the average time. Then run the same script via PHP CLI 3 times and note down the average. If the difference is noticeable then you might blame XAMPP. You should be able to locate the PHP CLI binary somewhere inside the XAMPP installation folder.
On my system I get these results:
PHP-CLI: #10001: 104743 -- Time taken: 30.25 second(s)
PHP on IIS/FastCGI: #10001: 104743 -- Time taken: 29.89 second(s)
PHP on Apache/CGI: #10001: 104743 -- Time taken: 29.93 second(s)
Not much of a difference -- I would rather optimize the code.
EDIT
Same machine and everything but execution time brought down from ~30 seconds to ~5.85 seconds with this revised code. The only thing worth mentioning is that that I used a global array instead of passing it by value every time the isPrime function is called (104743 times to be precise). Passing the array by reference also results in similar execution time, give or take 1 second. The comparison operators shave off just a second or two but not much.
/*
* Project Euler #7:
* By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
* What is the 10001st prime number?
*/
ini_set('max_execution_time', 300);
$t0 = microtime(true);
$primes = array();
function isPrime($number)
{
global $primes;
foreach ($primes as $prime)
{
if ($prime === 1)
{
continue;
}
elseif ($number % $prime === 0)
{
return 0;
}
}
return $number;
}
$i = 0;
$nbPrimes = 0;
while ($nbPrimes < 10001)
{
$i++;
if ($i % 2 !== 0)
{
$result = isPrime($i);
if ($result !== 0)
{
$primes[] = $i;
$nbPrimes++;
}
}
}
$t1 = microtime(true);
echo sprintf('#%d: %d -- Time taken: %.2f second(s)', $nbPrimes, $result, $t1 - $t0);

Parsing EXIF's "ExposureTime" using PHP

Re,
One photo with exposure being 1/640 has the EXIF field of "ExposureTime" eq. "15625/10000000". I am not sure why some photos display this value in a readable format (e.g., "1/100"), but I need to convert this "15625" back to "1/640". How? :)
Thanks.
It's simple mathematics: simply divide the top and bottom of the fraction by the top value.
15625 / 10000000
= (15625/15625) / (10000000/15625)
= 1 / 640
In PHP, you can do it like this:
$exposure = "15625/10000000";
$parts = explode("/", $exposure);
$exposure = implode("/", array(1, $parts[1]/$parts[0]));
echo $exposure;
I improved upon ZZ Coders implementation with a few sanity checks and special cases. It seems to work well with my images with several special cases thrown at it. Please let me know if there are any issues and we'll improve it.
// Exposure Time
$exif = exif_read_data($fullPath, 'IFD0', true);
$arrExposureTime = explode('/', $exif['EXIF']['ExposureTime']);
// Sanity check for zero denominator.
if ($arrExposureTime[1] == 0) {
$ExposureTime = '<sup>1</sup>/? sec';
// In case numerator is zero.
} elseif ($arrExposureTime[0] == 0) {
$ExposureTime = '<sup>0</sup>/' . $arrExposureTime[1] . ' sec';
// When denominator is 1, display time in whole seconds, minutes, and/or hours.
} elseif ($arrExposureTime[1] == 1) {
// In the Seconds range.
if ($arrExposureTime[0] < 60) {
$ExposureTime = $arrExposureTime[0] . ' s';
// In the Minutes range.
} elseif (($arrExposureTime[0] >= 60) && ($arrExposureTime[0] < 3600)) {
$ExposureTime = gmdate("i\m:s\s", $arrExposureTime[0]);
// In the Hours range.
} else {
$ExposureTime = gmdate("H\h:i\m:s\s", $arrExposureTime[0]);
}
// When inverse is evenly divisable, show reduced fractional exposure.
} elseif (($arrExposureTime[1] % $arrExposureTime[0]) == 0) {
$ExposureTime = '<sup>1</sup>/' . $arrExposureTime[1]/$arrExposureTime[0] . ' sec';
// If the value is greater or equal to 3/10, which is the smallest standard
// exposure value that doesn't divid evenly, show it in decimal form.
} elseif (($arrExposureTime[0]/$arrExposureTime[1]) >= 3/10) {
$ExposureTime = round(($arrExposureTime[0]/$arrExposureTime[1]), 1) . ' sec';
// If all else fails, just display it as it was found.
} else {
$ExposureTime = '<sup>' . $arrExposureTime[0] . '</sup>/' . $arrExposureTime[1] . ' sec';
}
This is the code I use to normalize the exposure,
if (($bottom % $top) == 0) {
$data = '1/'.round($bottom/$top, 0).' sec';
} else {
if ($bottom == 1) {
$data = $top.' sec';
} else {
$data = $top.'/'.$bottom.' sec';
}
}
It handles most exposures correctly but I see some weird ones once a while.
You can use Euclid's algorithm to find the greatest common divisor, which will help you reduce the fraction.

Categories