align decimals in array of currency values - php

I've tried to write a function that will take an array of different amounts and align the decimal places, by adding the appropriate amount of to each number with a lesser length than the number with longest length.
It seems pretty long though, and I wonder if anyone has some insight on how I could make is shorter and more efficient.
$arr = array(12, 34.233, .23, 44, 24334, 234);
function align_decimal ($arr) {
$long = 0;
$len = 0;
foreach ( $arr as &$i ){
//change array elements to string
(string)$i;
//if there is no decimal, add '.00'
//if there is a decimal, add '00'
//ensures that there are always at least two zeros after the decimal
if ( strrpos( $i, "." ) === false ) {
$i .= ".00";
} else {
$i .= "00";
}
//find the decimal
$dec = strrpos( $i, "." );
//ensure there are only two decimals
//$dec+3 is the decimal plus two characters
$i = substr_replace($i, "", $dec+3);
//if $i is longer than $long, set $long to $i
if ( strlen($i) >= strlen($long) ) {
$long = $i;
}
}
//locate the decimal in the longest string
$long_dec = strrpos( $long, "." );
foreach ( $arr as &$i ) {
//difference between $i and $long position of the decimal
$z = ( $long_dec - strrpos( $i, "." ) );
$c = 0;
while ( $c <= $z ) {
//add a for each number of characters
//between the two decimal locations
$i = " " . $i;
$c++;
}
}
return $arr;
}
it works okkaaay... just seems really verbose. I'm sure there are a million ways to make it much shorter and more professional. Thanks for any ideas!

Code:
$array = array(12, 34.233, .23, 44, 24334, 234);;
foreach($array as $value) $formatted[] = number_format($value, 2, '.', '');
$length = max(array_map('strlen', $formatted));
foreach($formatted as $value)
{
echo str_repeat(" ",$length-strlen($value)).$value."<br>";
}
Output:
12.00<br>
34.23<br>
0.23<br>
44.00<br>
24334.00<br>
234.00<br>
Rendered by browser:
12.00
34.23
0.23
44.00
24334.00
234.00

Is using a space a requirement for the display? If you don't mind having "30" coming out as "30.000" you could use the number_format to do most of the work for you, after you figured out the max number of decimal places to use.
$item = "40";
$len = 10;
$temp = number_format($item,$len);
echo $temp;
Another would be to use sprintf to format:
$item = "40";
$len = 10;
$temp = sprintf("%-{$len}s", $item);
$temp = str_replace(' ', ' ',$temp);
echo $temp;

Have you considered using HTML elements alongside CSS alignment to do this for you?
For instance:
<div style="display:inline-block; text-align:right;">$10.00<br />$1234.56<div>
This would ease the issue of using spaces to manually adjust the alignment. Since you're aligning to the right and there are two decimal places, the decimals will line up as you wish. You could also do this using a <table> and in both scenarios, you're able to simply retrieve the full value through JS if need be.
Lastly, using spaces assumes you're using a fixed-width font which may not necessarily be the case. CSS alignment allows you to handle this much more eloquently.

Related

Need to convert the floating values to integer format below the condition in php

Need to convert the floating values to integer format below the condition
$val = 75.00 means the value must be show 75
$val = 75.50 means the values must be show 75.50
the floating points values .00 means no need to display otherwise will display with floating values.
is possible in php?
Try this code:
$val = 75.00;
$value = explode(".", $val);
$decimal_value = substr($value[0], 0, 1);
if($decimal_value == "00"){
$val = $value[0];
} else {
$val = number_format($val, 2, '.', '');
}
echo $val;
$val + 0 does the trick.
echo 75.00 + 0; // 75
echo 75.50 + 0; // 75.5
Internally, this is equivalent to casting to float with (float)$val or floatval($val) but I find it simpler.
(float) $val;
In finally use below the code.
$ans = (float)$val;
echo $ans; means it working perfectly.

One-line PHP random string generator?

I am looking for the shortest way to generate random/unique strings and for that I was using the following two:
$cClass = sha1(time());
or
$cClass = md5(time());
However, I need the string to begin with a letter, I was looking at base64 encoding but that adds == at the end and then I would need to get rid of that.
What would be the best way to achieve this with one line of code?
Update:
PRNDL came up with a good suggestions which I ended up using it but a bit modified
echo substr(str_shuffle(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ),0, 1) . substr(str_shuffle(aBcEeFgHiJkLmNoPqRstUvWxYz0123456789),0, 31)
Would yield 32 characters mimicking the md5 hash but it would always product the first char an alphabet letter, like so;
However, Uours really improved upon and his answer;
substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1).substr(md5(time()),1);
is shorter and sweeter
The other suggestion by Anonymous2011 was very awesome but the first character for some reason would always either M, N, Y, Z so didn't fit my purposes but would have been the chosen answer, by the way does anyone know why it would always yield those particular letters?
Here is the preview of my modified version
echo rtrim(base64_encode(md5(microtime())),"=");
Rather than shuffling the alphabet string , it is quicker to get a single random char .
Get a single random char from the string and then append the md5( time( ) ) to it . Before appending md5( time( ) ) remove one char from it so as to keep the resulting string length to 32 chars :
substr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", mt_rand(0, 51), 1).substr(md5(time()), 1);
Lowercase version :
substr("abcdefghijklmnopqrstuvwxyz", mt_rand(0, 25), 1).substr(md5(time()), 1);
Or even shorter and a tiny bit faster lowercase version :
chr(mt_rand(97, 122)).substr(md5(time()), 1);
/* or */
chr(mt_rand(ord('a'), ord('z'))).substr(md5(time()), 1);
A note to anyone trying to generate many random strings within a second: Since time( ) returns time in seconds , md5( time( ) ) will be same throughout a given second-of-time due to which if many random strings were generated within a second-of-time, those probably could end up having some duplicates .
I have tested using below code . This tests lower case version :
$num_of_tests = 100000;
$correct = $incorrect = 0;
for( $i = 0; $i < $num_of_tests; $i++ )
{
$rand_str = substr( "abcdefghijklmnopqrstuvwxyz" ,mt_rand( 0 ,25 ) ,1 ) .substr( md5( time( ) ) ,1 );
$first_char_of_rand_str = substr( $rand_str ,0 ,1 );
if( ord( $first_char_of_rand_str ) < ord( 'a' ) or ord( $first_char_of_rand_str ) > ord( 'z' ) )
{
$incorrect++;
echo $rand_str ,'<br>';
}
else
{
$correct++;
}
}
echo 'Correct: ' ,$correct ,' . Incorrect: ' ,$incorrect ,' . Total: ' ,( $correct + $incorrect );
I had found something like this:
$length = 10;
$randomString = substr(str_shuffle(md5(time())),0,$length);
echo $randomString;
If you need it to start with a letter, you could do this. It's messy... but it's one line.
$randomString = substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1) . substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);
echo $randomString;
I decided this question needs a better answer. Like code golf! This also uses a better random byte generator.
preg_replace("/[\/=+]/", "", base64_encode(openssl_random_pseudo_bytes(8)));
Increase the number of bytes for a longer password, obviously.
Creates a 200 char long hexdec string:
$string = bin2hex(openssl_random_pseudo_bytes(100));
maaarghk's answer is better though.
base_convert(microtime(true), 10, 36);
You can try this:
function KeyGenerator($uid) {
$tmp = '';
for($z=0;$z<5;$z++) {
$tmp .= chr(rand(97,122)) . rand(0,100);
}
$tmp .= $uid;
return $tmp;
}
I have generated this code for you. Simple, short and (resonably) elegant.
This uses the base64 as you mentioned, if length is not important to you - However it removes the "==" using str_replace.
<?php
echo str_ireplace("==", "", base64_encode(time()));
?>
I use this function
usage:
echo randomString(20, TRUE, TRUE, FALSE);
/**
* Generate Random String
* #param Int Length of string(50)
* #param Bool Upper Case(True,False)
* #param Bool Numbers(True,False)
* #param Bool Special Chars(True,False)
* #return String Random String
*/
function randomString($length, $uc, $n, $sc) {
$rstr='';
$source = 'abcdefghijklmnopqrstuvwxyz';
if ($uc)
$source .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if ($n)
$source .= '1234567890';
if ($sc)
$source .= '|##~$%()=^*+[]{}-_';
if ($length > 0) {
$rstr = "";
$length1= $length-1;
$input=array('a','b','c','d','e','f','g','h','i','j,''k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')
$rand = array_rand($input, 1)
$source = str_split($source, 1);
for ($i = 1; $i <= $length1; $i++) {
$num = mt_rand(1, count($source));
$rstr1 .= $source[$num - 1];
$rstr = "{$rand}{$rstr1}";
}
}
return $rstr;
}
I'm using this one to generate dozens of unique strings in a single go, without repeating them, based on other good examples above:
$string = chr(mt_rand(97, 122))
. substr(md5(str_shuffle(time() . rand(0, 999999))), 1);
This way, I was able to generate 1.000.000 unique strings in ~5 seconds. It's not THAT fast, I know, but as I just need a handful of them, I'm ok with it. By the way, generating 10 strings took less than 0.0001 ms.
JavaScript Solution:
function randomString(pIntLenght) {
var strChars = “0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz”;
var strRandomstring = ”;
for (var intCounterForLoop=0; intCounterForLoop < pIntLenght; intCounterForLoop++) {
var rnum = Math.floor(Math.random() * strChars.length);
strRandomstring += strChars.substring(rnum,rnum+1);
}
return strRandomstring;
}
alert(randomString(20));
Reference URL : Generate random string using JavaScript
PHP Solution:
function getRandomString($pIntLength = 30) {
$strAlphaNumericString = ’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;
$strReturnString = ”;
for ($intCounter = 0; $intCounter < $pIntLength; $intCounter++) {
$strReturnString .= $strAlphaNumericString[rand(0, strlen($strAlphaNumericString) - 1)];
}
return $strReturnString;
}
echo getRandomString(20);
Reference URL : Generate random String using PHP
This function returns random lowercase string:
function randomstring($len=10){
$randstr='';
for($iii=1; $iii<=$len; $iii++){$randstr.=chr(rand(97,122));};
return($randstr);
};
I find that base64 encoding is useful for creating random strings, and use this line:
base64_encode(openssl_random_pseudo_bytes(9));
It gives me a random string of 12 positions, with the additional benefit that the randomness is "cryptographically strong".
to generate strings consists of random characters, you can use this function
public function generate_random_name_for_file($length=50){
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
It really depends on your requirements.
I needed strings to be unique between test runs, but not many other restrictions.
I also needed my string to start with a character, and this was good enough for my purpose.
$mystring = "/a" . microtime(true);
Example output:
a1511953584.0997
How to match the OPs original request in an awful way (expanded for readability):
// [0-9] ASCII DEC 48-57
// [A-Z] ASCII DEC 65-90
// [a-z] ASCII DEC 97-122
// Generate: [A-Za-z][0-9A-Za-z]
$r = implode("", array_merge(array_map(function($a)
{
$a = [rand(65, 90), rand(97, 122)];
return chr($a[array_rand($a)]);
}, array_fill(0, 1, '.')),
array_map(function($a)
{
$a = [rand(48, 57), rand(65, 90), rand(97, 122)];
return chr($a[array_rand($a)]);
}, array_fill(0, 7, '.'))));
One the last array_fill() would would change the '7' to your length - 1.
For one that does all alpha-nurmeric (And still slow):
// [0-9A-Za-z]
$x = implode("", array_map(function($a)
{
$a = [rand(48, 57), rand(65, 90), rand(97, 122)];
return chr($a[array_rand($a)]);
}, array_fill(0, 8, '.')));
The following one-liner meets the requirements in your question: notably, it begins with a letter.
substr("abcdefghijklmnop",random_int(0, 16),1) . bin2hex(random_bytes(15))
If you didn't care whether the string begins with a letter, you could just use:
bin2hex(random_bytes(16))
Note that here we use random_bytes and random_int, which were introduced in PHP 7 and use cryptographic random generators, something that is important if you want unique strings to be hard to guess. Many other solutions, including those involving time(), microtime(), uniqid(), rand(), mt_rand(), str_shuffle(), array_rand(), and shuffle(), are much more predictable and are unsuitable if the random string will serve as a password, a bearer credential, a nonce, a session identifier, a "verification code" or "confirmation code", or another secret value.
I also list other things to keep in mind when generating unique identifiers, especially random ones.
True one liner random string options:
implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21));
md5(microtime() . implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21)));
sha1(microtime() . implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21)));

Increment through A-Za-z0-9 in expanding string with PHP

I'm trying to generate strings in PHP with a group of valid characters, cycling through them and appending an extra character on the end of the string, until maximum length is reached. For example, desired output:
a,b,c,d,e,f,aa,ab,ac,ad,ae,af,ba,bb,bc,bd,be,bf,ca,cb..etc
This is my PHP function so far:
<?php
$chars = Array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','X','Y','Z',
'1','2','3','4','5','6','7','8','9','0');
$maxlen = 10;
$input = $chars[0];
while (1):
echo buildInput($maxlen, $chars, $input) . "\n";
endwhile;
function buildInput($maxlen, $chars, $previous)
{
if (array_search(substr($previous, -1), $chars) == sizeof($chars) - 1):
// end of input cycle reached, add another character
$previous = $previous . $chars[0];
endif;
if (strlen($previous) > $maxlen):
die('Max length reached');
endif;
// Remove last character, and append incremented char
$input = substr($previous, 0, -1);
$input = $input . $chars[array_search(substr($previous, -1), $chars)+1];
return $input;
}
?>
It only increments the last character of the string which gets to 0, then appends 'a' and starts over but without trying all the other possible permutations.
Could someone help me with a better method?
Is this the kind of thing you want?
<?php
$chars = array('a','b','c');
$max_length = 3;
function build($base_arr, $ctr) {
global $chars;
global $max_length;
$combos = array();
foreach ($base_arr as $base) {
foreach ($chars as $char) {
echo $base, $char, '<br />';
$combos[] = $base.$char;
}
}
if ($ctr < $max_length) {
build($combos, $ctr + 1);
}
}
foreach ($chars as $char) {
echo $char, '<br />';
}
build($chars, 2);
?>
It'll give you: a, b, c, aa, ab, ac, ba, bb, bc, ca, cb, cc, ..., bcc, caa, cab, cac, cba, cbb, cbc, cca, ccb, ccc.
Your array is so large, though, that using this method on it would take up way too much memory to work. Out of 62 characters (A-Z, a-z, 0-9), the number of possible 10-character permutations is 8.4 x 10^17; so hopefully, you'll be able to find a more efficient method or figure out a way to get the result you want without having to cycle through such a large array. I hope you find what you're looking for!
If you limit yourself to 0-9,a-z (only lower case), then you could use base_convert for this and do it in one line:
for($i = 0; $i < 1000; $i++) echo base_convert($i, 10, 36) . '<br/>';
Here's a demo.
This will print 200 letters: a,b,c,d,...,aa,...,cq
The buildString function will build our string from the least significant number (right) to the most significant (left). By performing a modulus division, you will find the array position of the next character. Add this character to the front of your string, and divide
your number by the size of your array (which is the base number in your character based number system), ignoring the rest.
To explain the method using our normal 10-based number system and the input of 123, you would simply pick the last digit, 3, divide the input by 10, pick the last digit 2, divide the input by 10, pick the last digit 1, divide the input by 10. The input is now 0 and your output is ready...
$chars = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q'
,'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J'
,'K','L','M','N','O','P','Q','R','S','T','U','V','X','Y','Z','1','2','3','4'
,'5','6','7','8','9','0');
$numChars = count($chars);
// Output numbers from 1 to 200 (a to cq)
for($i = 1; $i <= 200; $i++) {
echo buildString($i).'<br>';
}
// Will also work fine for large numbers - output "dxSA"
echo buildString(1000000).'<br>';
function buildString($int) {
global $chars;
global $numChars;
$output = '';
while($int) {
$output = $chars[($int-1) % $numChars] . $output;
$int = floor(($int-1) / $numChars);
}
return $output;
}
If you have access to gmp extension and PHP 5.3.2+ this will work for the charset you specified:
$result = strtr(
gmp_strval(gmp_init($i, 10), 62),
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
);

How to create array for possible probability (combinations) for given number in php

I am having mathematics oriented question.Here i like to get the all possible combinations
and looking to store in array.
For example:-
1 digit = 10 (0,1,2,3,....9)
2 digit = 100 (00,01,02,03,...)
I am having formula to find number of possibilities i.e 10^n -1.But i don't know how can i get the values.
function get_combinations(5){
//10^5 -1 = 99999 values
}
the function result should be
00000,00001,00010,00100,....
in array
not like
0,1,2,....00,01,03,...99999
EDIT
I also like to mix some alphabets with the number
results like
0000a,000a1,000z1,00001,00000,....
Thanks in advance
$n = ???;
$array = range(0, pow(10, $n)-1);
yes, there is no integer start with zero
so, dun bother to construct an array start with leading zero,
when you need to output str_pad can be applied
function get_combinations($n)
{
return range(0, pow(10, $n)-1);
}
$array = get_combinations(5);
$pad = strlen(max($array));
// to output
echo str_pad($array[0], $pad, 0, STR_PAD_LEFT);
$result = array();
$count = pow(10,$x);
for ($i = 0, $i < $count, $i++) {
$result[] = str_repeat('0', $x - strlen($i)) . $i;
}
You can't have an integer that is 0000 because that is just 0.
To get all numbers from 0 to 9 use the range() function:
$array = range(0,9); // array(0,1,2,3,4,5,6,7,8,9)
And alike for bigger numbers.
If you want them as strings use sprintf or related to reformat that array.
Or just use a for( loop :)
How about:
$n = 3;
function format($x) {
global $n;
return sprintf("%0${n}d", $x);
}
$arr = array_map('format', range(0, pow(10,$n)-1));
function get_combinations($exp){
$max = pow(10, $exp) - 1;
for ($i = 0; $i <= $max; $i++) $comb[] = str_pad($i, $exp, '0', STR_PAD_LEFT);
return $comb;
}

Algorithms for string similarities (better than Levenshtein, and similar_text)? Php, Js

Where can I find algorithms that values the spelling of misplaced characters more accurately than levenshtein() and php similar_text() methods?
Example:
similar_text('jonas', 'xxjon', $similar); echo $similar; // returns 60
similar_text('jonas', 'asjon', $similar); echo $similar; // returns 60 <- although more similar!
echo levenshtein('jonas', 'xxjon'); // returns 4
echo levenshtein('jonas', 'asjon'); // returns 4 <- although more similar!
/ Jonas
Here's a solution that I've come up to. It's based on Tim's suggestion of comparing the order of subsequent charachters. Some results:
jonas / jonax : 0.8
jonas / sjona : 0.68
jonas / sjonas : 0.66
jonas / asjon : 0.52
jonas / xxjon : 0.36
I'm sure i isn't perfect, and that it could be optimized, but nevertheless it seems to produce the results that I'm after...
One weak spot is that when strings have different length, it produces different result when the values are swapped...
static public function string_compare($str_a, $str_b)
{
$length = strlen($str_a);
$length_b = strlen($str_b);
$i = 0;
$segmentcount = 0;
$segmentsinfo = array();
$segment = '';
while ($i < $length)
{
$char = substr($str_a, $i, 1);
if (strpos($str_b, $char) !== FALSE)
{
$segment = $segment.$char;
if (strpos($str_b, $segment) !== FALSE)
{
$segmentpos_a = $i - strlen($segment) + 1;
$segmentpos_b = strpos($str_b, $segment);
$positiondiff = abs($segmentpos_a - $segmentpos_b);
$posfactor = ($length - $positiondiff) / $length_b; // <-- ?
$lengthfactor = strlen($segment)/$length;
$segmentsinfo[$segmentcount] = array( 'segment' => $segment, 'score' => ($posfactor * $lengthfactor));
}
else
{
$segment = '';
$i--;
$segmentcount++;
}
}
else
{
$segment = '';
$segmentcount++;
}
$i++;
}
// PHP 5.3 lambda in array_map
$totalscore = array_sum(array_map(function($v) { return $v['score']; }, $segmentsinfo));
return $totalscore;
}
In addition to levenshtein() and similar_text(), there's also:
soundex(): Returns the four-character soundex key of a word, which should be the same as the key for any similar-sounding word.
metaphone(): Similar to soundex, and possibly more effective for you. It's more accurate than soundex() as it knows the basic rules of English pronunciation. The metaphone generated keys are of variable length.
Please, be careful about using string_compare :
ivanov ivan / ivanov ivan : 1 OK!
ivanov ivan2 / ivanov ivan : 1 o_O
ivanov ivan / ivanov i : 1.1363636363636 OMG!
I've found that Jaro Winkler is also good for spelling mistakes and small differences between strings. I modified this code to be object-oriented:
class StringCompareJaroWinkler
{
public function compare($str1, $str2)
{
return $this->JaroWinkler($str1, $str2, $PREFIXSCALE = 0.1 );
}
private function getCommonCharacters( $string1, $string2, $allowedDistance ){
$str1_len = mb_strlen($string1);
$str2_len = mb_strlen($string2);
$temp_string2 = str_split($string2);
$commonCharacters='';
for( $i=0; $i < $str1_len; $i++){
$noMatch = True;
// compare if char does match inside given allowedDistance
// and if it does add it to commonCharacters
for( $j= max( 0, $i-$allowedDistance ); $noMatch && $j < min( $i + $allowedDistance + 1, $str2_len ); $j++){
if( $temp_string2[$j] == $string1[$i] ){
$noMatch = False;
$commonCharacters .= $string1[$i];
$temp_string2[$j] = '';
}
}
}
return $commonCharacters;
}
private function Jaro( $string1, $string2 ){
$str1_len = mb_strlen( $string1 );
$str2_len = mb_strlen( $string2 );
// theoretical distance
$distance = (int) floor(min( $str1_len, $str2_len ) / 2.0);
// get common characters
$commons1 = $this->getCommonCharacters( $string1, $string2, $distance );
$commons2 = $this->getCommonCharacters( $string2, $string1, $distance );
if( ($commons1_len = mb_strlen( $commons1 )) == 0) return 0;
if( ($commons2_len = mb_strlen( $commons2 )) == 0) return 0;
// calculate transpositions
$transpositions = 0;
$upperBound = min( $commons1_len, $commons2_len );
for( $i = 0; $i < $upperBound; $i++){
if( $commons1[$i] != $commons2[$i] ) $transpositions++;
}
$transpositions /= 2.0;
// return the Jaro distance
return ($commons1_len/($str1_len) + $commons2_len/($str2_len) + ($commons1_len - $transpositions)/($commons1_len)) / 3.0;
}
private function getPrefixLength( $string1, $string2, $MINPREFIXLENGTH = 4 ){
$n = min( array( $MINPREFIXLENGTH, mb_strlen($string1), mb_strlen($string2) ) );
for($i = 0; $i < $n; $i++){
if( $string1[$i] != $string2[$i] ){
// return index of first occurrence of different characters
return $i;
}
}
// first n characters are the same
return $n;
}
private function JaroWinkler($string1, $string2, $PREFIXSCALE = 0.1 ){
$JaroDistance = $this->Jaro( $string1, $string2 );
$prefixLength = $this->getPrefixLength( $string1, $string2 );
return $JaroDistance + $prefixLength * $PREFIXSCALE * (1.0 - $JaroDistance);
}
}
$jw = new StringCompareJaroWinkler();
echo $jw->compare("jonas","asjon");
#Tim: I'm actually looking for a way
to process/measure similarities in a
pedagogical game context. Let's say
that a student's task is to select
objects from a pool, and put those
objects in a specific order (sort them
by alphabet or whatever). I then need
a way to measure the similarity
between the students answer and the
correct one
Algorithms to calculate the degree-of-correctness of the order of characters in a word (i.e. its spelling) could be very different from an algorithm to measure the correct order of words in a list. The way spelling algorithms handle omissions or dittography or transpositions might not apply very well to your use case.
If you know the order of elements in advance, and know the number of elements too, then you could simply loop through the answer and compare value-at-position to correct-value-at-position and arrive at a percentage-correct. Yet that would be a crude measure, and misleading, for if the goal of your game was to test, say, whether the gamer understood alphabetic sorting, and the gamer happened to get the first word wrong, every word could be in the wrong position even if the words were in otherwise correct alphabetic order:
banana
blackberry
blueberry
cherry
fig
grapefruit
orange
pear
persimmon
raspberry
apple
So what you could do to improve the accuracy of your measurement in our hypothetical situation is this: loop through the gamer's answer-list looking to see if the answer value is immediately followed by the correct word; every time a word is followed by the correct word, you would give the gamer a point. The gamer who produced the list above would get 9 points out of a possible 10 and that score would indeed accurately reflect the gamer's understanding of the rules of alphabetic sorting.

Categories