I've been tasked with porting a small internal company formula/algorithm from Java to PHP, and have for the most part been successful, but am clearly going wrong somewhere because I'm not getting the same output from my ported version than I am from the PHP version. I'm relatively new to PHP and don't know anything about Java, so I'm guessing I'm missing a subtle but crucial difference in how the two languages do maths, particularly on the line with the double
and floor()
function.
Here is the original Java code, which needs to take user input in the format F999
and generate a four-digit output:
String input;
String Generate() {
int charAt = (((this.input.charAt(0) * 5) * 2) - 698) + this.input.charAt(1);
int charAt2 = ((((this.input.charAt(2) * 5) * 2) + charAt) + this.input.charAt(3)) - 528;
charAt2 = ((charAt2 << 3) - charAt2) % 100;
String valueOf = String.valueOf((((((259 % charAt) % 100) * 5) * 5) * 4) + ((((charAt2 % 10) * 5) * 2) + ((int) Math.floor((double) (charAt2 / 10)))));
return valueOf.length() == 3 ? "0" + valueOf : valueOf.length() == 2 ? "00" + valueOf : valueOf.length() == 1 ? "000" + valueOf : valueOf;
}
And here is my ported PHP version of it, currently simulating user input using a string:
$input = "F999"; # should output 2360
$charAt = ((((int) $input[0] * 5) * 2) - 698) + $input[1];
$charAt2 = (((($input[2] * 5) * 2) + $charAt) + $input[3]) - 528;
$charAt2 = (($charAt2 << 3) - $charAt2) % 100;
$valueOf = strval(((((((259 % $charAt) % 100) * 5) * 5) * 4) + (((($charAt2 % 10) * 5) * 2) + ((int) floor((double) ($charAt2 / 10))))));
if (strlen($valueOf) == 3) $valueOf = '0' . $valueOf;
elseif (strlen($valueOf) == 2) $valueOf = '00' . $valueOf;
elseif (strlen($valueOf) == 1) $valueOf = '000' . $valueOf;
return $valueOf; # currently outputs 5837
What does the Java source have that my PHP code is missing?
The problem is caused by the following difference:
charAt
returns result as an integer type char
, which is an unsigned integer from 0 to 65535.[]
returns result as a character.Thus, in Java this.input.charAt(0)
returns an ASCII code of 'F', i.e. 70.
In PHP $input[0]
returns a character 'F', which cannot be converted directly to int. So, in PHP (int)('F')
is just 0. In order to get an ASCII code of a symbol in PHP use ord()
. For example:
$input = "F999"; # should output 2360
$charAt = (((ord($input[0]) * 5) * 2) - 698) + ord($input[1]);
$charAt2 = ((((ord($input[2]) * 5) * 2) + $charAt) + ord($input[3])) - 528;
$charAt2 = (($charAt2 << 3) - $charAt2) % 100;
$valueOf = strval(((((((259 % $charAt) % 100) * 5) * 5) * 4) + (((($charAt2 % 10) * 5) * 2) + ((int) floor((double) ($charAt2 / 10))))));
if (strlen($valueOf) == 3) $valueOf = '0' . $valueOf;
elseif (strlen($valueOf) == 2) $valueOf = '00' . $valueOf;
elseif (strlen($valueOf) == 1) $valueOf = '000' . $valueOf;
return $valueOf;
Here is a demo.