Number to words in devnagri - php

I have to display result as
दुई खर्ब सतासी अर्ब अन्ठान्नब्बे करोड नब्बे लाख बाह्र हजार तीन सय पचहत्तर ...
It displays result correctly till five numbers..
But it doesn't display as needed when we use six numbers....
like 111111 .... It displays "एक सय एघार हजार एक सय एघार"
Where as it must be as "एक लाख एघार हजार एक सय एघार" .....
In case of seven and more numbers it throws error....
error 'Undefined offset: 1000000 in.....' ...
<?php
function convert_number_to_words($number) {
$hyphen = '-';
$conjunction = ' ';
$separator = ' ';
$negative = 'negative ';
$decimal = ' point ';
$dictionary = array(
0 => 'शुन्य',
1 => 'एक',
2 => 'दुई',
3 => 'तीन',
4 => 'चार',
5 => 'पाँच',
6 => 'छ',
7 => 'सात',
8 => 'आठ',
9 => 'नौ',
10 => 'दश',
11 => 'एघार',
12 => 'बाह्र',
13 => 'तेह्र',
14 => 'चौध',
15 => 'पन्ध',
16 => 'सोह्र',
17 => 'सत्र',
18 => 'अठार',
19 => 'उन्नाइस',
20 => 'विस',
21 => 'एक्काइस',
22 => 'बाइस',
23 => 'तेइस',
24 => 'चौविस',
25 => 'पच्चिस',
26 => 'छब्बिस',
27 => 'सत्ताइस',
28 => 'अठ्ठाईस',
29 => 'उनन्तिस',
30 => 'तिस',
31 => 'एकत्तिस',
32 => 'बत्तिस',
33 => 'तेत्तिस',
34 => 'चौँतिस ',
35 => 'पैँतिस',
36 => 'छत्तिस',
37 => 'सैँतीस',
38 => 'अठतीस',
39 => 'उनन्चालीस',
40 => 'चालीस',
41 => 'एकचालीस',
42 => 'बयालीस',
43 => 'त्रियालीस',
44 => 'चवालीस',
45 => 'पैँतालीस',
46 => 'छयालीस',
47 => 'सरचालीस',
48 => 'अठचालीस',
49 => 'उनन्चास',
50 => 'पचास',
51 => 'एकाउन्न',
52 => 'बाउन्न',
53 => 'त्रिपन्न',
54 => 'चउन्न',
55 => 'पचपन्न',
56 => 'छपन्न',
57 => 'सन्ताउन्न ',
58 => 'अन्ठाउन्न',
59 => 'उनन्साठी',
60 => 'साठी',
61 => 'एकसट्ठी',
62 => 'बयसट्ठी',
63 => 'त्रिसट्ठी',
64 => 'चौंसट्ठी',
65 => 'पैंसट्ठी',
66 => 'छयसट्ठी',
67 => 'सतसट्ठी',
68 => 'अठसट्ठी',
69 => 'उनन्सत्तरी',
70 => 'सत्तरी',
71 => 'एकहत्तर',
72 => 'बहत्तर',
73 => 'त्रिहत्तर',
74 => 'चौहत्तर',
75 => 'पचहत्तर',
76 => 'छयहत्तर',
77 => 'सतहत्तर',
78 => 'अठहत्तर',
79 => 'उनासी',
80 => 'असी',
81 => 'एकासी',
82 => 'बयासी',
83 => 'त्रियासी',
84 => 'चौरासी',
85 => 'पचासी',
86 => 'छयासी',
87 => 'सतासी',
88 => 'अठासी',
89 => 'उनान्नब्बे',
90 => 'नब्बे',
91 => 'एकान्नब्बे',
92 => 'बयानब्बे',
93 => 'त्रियान्नब्बे',
94 => 'चौरान्नब्बे',
95 => 'पन्चानब्बे',
96 => 'छयान्नब्बे',
97 => 'सन्तान्नब्बे',
98 => 'अन्ठान्नब्बे',
99 => 'उनान्सय',
100 => 'सय',
1000 => 'हजार',
100000 => 'लाख',
10000000 => 'करोड',
1000000000 => 'अर्ब',
100000000000 => 'खर्ब'
);
if (!is_numeric($number)) {
return false;
}
if (($number >= 0 && (int) $number < 0) || (int) $number < 0 -
PHP_INT_MAX) {
trigger_error(
'convert_number_to_words only accepts numbers between -' .
PHP_INT_MAX . ' and ' . PHP_INT_MAX,
E_USER_WARNING
);
return false;
}
if ($number < 0) {
return $negative . convert_number_to_words(abs($number));
}
$string = $fraction = null;
if (strpos($number, '.') !== false) {
list($number, $fraction) = explode('.', $number);
}
switch (true) {
case $number < 100:
$string = $dictionary[$number];
break;
case $number < 100:
$tens = ((int) ($number / 10)) * 10;
$units = $number % 10;
$string = $dictionary[$tens];
if ($units) {
$string .= $hyphen . $dictionary[$units];
}
break;
case $number < 1000:
$hundreds = $number / 100;
$remainder = $number % 100;
$string = $dictionary[$hundreds] . ' ' . $dictionary[100];
if ($remainder) {
$string .= $conjunction . convert_number_to_words($remainder);
}
break;;
default:
$baseUnit = pow(100000, floor(log($number, 100000)));
$numBaseUnits = (int) ($number / $baseUnit);
$remainder = $number % $baseUnit;
$string = convert_number_to_words($numBaseUnits) . ' ' .
$dictionary[$baseUnit];
if ($remainder) {
$string .= $remainder < 100 ? $conjunction : $separator;
$string .= convert_number_to_words($remainder);
}
break;
}
if (null !== $fraction && is_numeric($fraction)) {
$string .= $decimal;
$words = array();
foreach (str_split((string) $fraction) as $number) {
$words[] = $dictionary[$number];
}
$string .= implode(' ', $words);
}
return $string;
}
?>
Page "numtoword.php"
Page "index.php"
<?php
include('numword.php');
echo convert_number_to_words(287989012375);
?>

It looks like you are making it more difficult than it needs to be. I created a simpler recursive function, moved the dictionary and settings outside the function (generating a dictionary array on every function call was eating up a LOT of memory and is not necessary). I didn't include fractions but this should be a good starting point to expand off of:
<?php
$devnagriNumeralWords = [
'dictionary' => [
'smallUnits' => [
0 => 'शुन्य',
1 => 'एक',
2 => 'दुई',
3 => 'तीन',
4 => 'चार',
5 => 'पाँच',
6 => 'छ',
7 => 'सात',
8 => 'आठ',
9 => 'नौ',
10 => 'दश',
11 => 'एघार',
12 => 'बाह्र',
13 => 'तेह्र',
14 => 'चौध',
15 => 'पन्ध',
16 => 'सोह्र',
17 => 'सत्र',
18 => 'अठार',
19 => 'उन्नाइस',
20 => 'विस',
21 => 'एक्काइस',
22 => 'बाइस',
23 => 'तेइस',
24 => 'चौविस',
25 => 'पच्चिस',
26 => 'छब्बिस',
27 => 'सत्ताइस',
28 => 'अठ्ठाईस',
29 => 'उनन्तिस',
30 => 'तिस',
31 => 'एकत्तिस',
32 => 'बत्तिस',
33 => 'तेत्तिस',
34 => 'चौँतिस ',
35 => 'पैँतिस',
36 => 'छत्तिस',
37 => 'सैँतीस',
38 => 'अठतीस',
39 => 'उनन्चालीस',
40 => 'चालीस',
41 => 'एकचालीस',
42 => 'बयालीस',
43 => 'त्रियालीस',
44 => 'चवालीस',
45 => 'पैँतालीस',
46 => 'छयालीस',
47 => 'सरचालीस',
48 => 'अठचालीस',
49 => 'उनन्चास',
50 => 'पचास',
51 => 'एकाउन्न',
52 => 'बाउन्न',
53 => 'त्रिपन्न',
54 => 'चउन्न',
55 => 'पचपन्न',
56 => 'छपन्न',
57 => 'सन्ताउन्न ',
58 => 'अन्ठाउन्न',
59 => 'उनन्साठी',
60 => 'साठी',
61 => 'एकसट्ठी',
62 => 'बयसट्ठी',
63 => 'त्रिसट्ठी',
64 => 'चौंसट्ठी',
65 => 'पैंसट्ठी',
66 => 'छयसट्ठी',
67 => 'सतसट्ठी',
68 => 'अठसट्ठी',
69 => 'उनन्सत्तरी',
70 => 'सत्तरी',
71 => 'एकहत्तर',
72 => 'बहत्तर',
73 => 'त्रिहत्तर',
74 => 'चौहत्तर',
75 => 'पचहत्तर',
76 => 'छयहत्तर',
77 => 'सतहत्तर',
78 => 'अठहत्तर',
79 => 'उनासी',
80 => 'असी',
81 => 'एकासी',
82 => 'बयासी',
83 => 'त्रियासी',
84 => 'चौरासी',
85 => 'पचासी',
86 => 'छयासी',
87 => 'सतासी',
88 => 'अठासी',
89 => 'उनान्नब्बे',
90 => 'नब्बे',
91 => 'एकान्नब्बे',
92 => 'बयानब्बे',
93 => 'त्रियान्नब्बे',
94 => 'चौरान्नब्बे',
95 => 'पन्चानब्बे',
96 => 'छयान्नब्बे',
97 => 'सन्तान्नब्बे',
98 => 'अन्ठान्नब्बे',
99 => 'उनान्सय'
],
'largeUnits' => [
100 => 'सय',
1000 => 'हजार',
100000 => 'लाख',
10000000 => 'करोड',
1000000000 => 'अर्ब',
100000000000 => 'खर्ब'
]
],
'hyphen' => '-',
'conjunction' => ' ',
'separator' => ' ',
'negative' => 'negative ',
'decimal' => ' point '
];
function convert_devnagri_number_to_words($number) {
global $devnagriNumeralWords;
$numLen = strlen($number);
$output = [ 'prefix' => '', 'base' => '', 'suffix' => '' ];
$base = pow(10, $numLen-1);
$smallestLargeUnit = array_keys($devnagriNumeralWords['dictionary']['largeUnits'])[0];
$isNegative = $number < 0;
if( $isNegative ) {
$output['prefix'] .= $devnagriNumeralWords['negative'];
$number = abs($number);
}
if( $number < $smallestLargeUnit ) {
// Number is less than 100
$prefix = $number;
} else {
// Get base amount (100, 1000, 100000, etc)
if( isset($devnagriNumeralWords['dictionary']['largeUnits'][$base]) ) {
$largeUnit = $devnagriNumeralWords['dictionary']['largeUnits'][$base];
} else {
// No exact large unit match, find next smallest
while( $base >= $smallestLargeUnit ) {
$base = (int) ($base / 10);
if( isset($devnagriNumeralWords['dictionary']['largeUnits'][$base]) ) {
break; // Found a match!
}
}
}
$output['base'] .= $devnagriNumeralWords['dictionary']['largeUnits'][$base];
// Get prefix, e.g. "28" when number is 28564
$prefix = (int) ($number / $base);
// Subtract prefix to get next part to process
// E.g. the next number is 345 when the number is 85345
$nextNumber = $number - ($prefix * $base);
if( $nextNumber > 0 )
$output['suffix'] = convert_devnagri_number_to_words($nextNumber);
}
if( $prefix >= 0 ) {
$output['prefix'] .= $devnagriNumeralWords['dictionary']['smallUnits'][$prefix];
}
// Put it all together!
return implode( $devnagriNumeralWords['separator'], array_filter($output) );
}
echo convert_devnagri_number_to_words(287989012375);

Related

preg_replace or preg_match and how can i define it right

This is my string:
$string = "format,surcharge,amount,1,card,basicprice 3,50 F010F020,0%,3,50 ,,,";
and i want to have an array which should look like this:
array(
0 => "format",
1 => "surcharge",
2 => "amount",
3 => "1",
4 => "card",
5 => "basicprice",
6 => "3,50", //<-- tricky part, i complete don't get how i can solve this
7 => "card",
8 => "F010", //<-- tricky part, i complete don't get how i can solve this
9 => "F020", //<-- tricky part, i complete don't get how i can solve this
10 => "3,50",
);
so my tries look like this:
$string = "Format,Aufpreis,Anzahl,1,Card,Basispreis 3,50 F010F020,0%,3,50 ,,,,,,";
$regEx = '/,/';
$replace = ' ';
$perfectArray = preg_replace('/,/', $replace, $string2);
var_dump($perfectArray);
or like this
$array = str_split($string);
$from = array(",", '"');
$to = array(" ", " ");
foreach ($array as $value)
{
$value = str_replace($from, $to, $string);
}
var_dump($value);
someone know how i can solve this? especially the "tricky part" (i put a comment in the code)
would be very nice if someone can answer :)
As mentioned in your comments, if this is coming from csv try using
fgetcsv function.
You can directly work on these values.
Have a look at it here http://php.net/manual/en/function.fgetcsv.php, the example explains pretty well
After you mentioned in comments that you have raw data in CSV format, the use of regular expression is not the best solution.
Instead split the data into an array with PHP's CSV functions, like str_getcsv:
$csv = 'F251,43%,"3,50 €","0,50 €","0,50 €",,"0,50 €","0,50 €","0,50 €","0,49 €",
"0,49 €",,"0,47 €",,"0,47 €",,"0,46 €","0,46 €","0,44 €","0,44 €","0,44 €",,
"0,43 €",,"0,43 €","0,43 €",,,"0,41 €",,,"0,40 €","0,40 €",,"0,39 €",
"0,39 €",,"0,37 €","0,37 €","0,36 €","0,36 €","0,36 €","0,36 €","0,36 €"';
$data = str_getcsv($csv);
var_export ($data);
Output:
array (
0 => 'F251',
1 => '43%',
2 => '3,50 €',
3 => '0,50 €',
4 => '0,50 €',
5 => '',
6 => '0,50 €',
7 => '0,50 €',
8 => '0,50 €',
9 => '0,49 €',
10 => '0,49 €',
11 => '',
12 => '0,47 €',
13 => '',
14 => '0,47 €',
15 => '',
16 => '0,46 €',
17 => '0,46 €',
18 => '0,44 €',
19 => '0,44 €',
20 => '0,44 €',
21 => '',
22 => '0,43 €',
23 => '',
24 => '0,43 €',
25 => '0,43 €',
26 => '',
27 => '',
28 => '0,41 €',
29 => '',
30 => '',
31 => '0,40 €',
32 => '0,40 €',
33 => '',
34 => '0,39 €',
35 => '0,39 €',
36 => '',
37 => '0,37 €',
38 => '0,37 €',
39 => '0,36 €',
40 => '0,36 €',
41 => '0,36 €',
42 => '0,36 €',
43 => '0,36 €',
)
If you would like to get rid of the € and % signs, and/or use the decimal point for numbers (to allow further calculations in PHP), then you could do this:
$data = array_map(function ($v) {
// get rid of `€` or `%` at the end of values:
$v = preg_replace('/( €|%)$/', '', $v);
// if you want to replace the decimal comma to point for further calculations:
$num = str_replace(',', '.', str_replace('.', '', $v));
return is_numeric($num) ? $num : $v;
}, $data);
var_export ($data);
Which outputs:
array (
0 => 'F251',
1 => '43',
2 => '3.50',
3 => '0.50',
4 => '0.50',
5 => '',
6 => '0.50',
7 => '0.50',
8 => '0.50',
9 => '0.49',
10 => '0.49',
11 => '',
12 => '0.47',
13 => '',
14 => '0.47',
15 => '',
16 => '0.46',
17 => '0.46',
18 => '0.44',
19 => '0.44',
20 => '0.44',
21 => '',
22 => '0.43',
23 => '',
24 => '0.43',
25 => '0.43',
26 => '',
27 => '',
28 => '0.41',
29 => '',
30 => '',
31 => '0.40',
32 => '0.40',
33 => '',
34 => '0.39',
35 => '0.39',
36 => '',
37 => '0.37',
38 => '0.37',
39 => '0.36',
40 => '0.36',
41 => '0.36',
42 => '0.36',
43 => '0.36',
)
Original answer based on regular expressions
You could do this with a regular expression, but it depends on what your rules are for splitting other strings. This regular expression assumes the string will always have the same number of items in the same order, and concerning the F010 and F020 it assumes that these always each occupy exactly 4 characters and are always present:
$string = "format,surcharge,amount,1,card,basicprice 3,50 F010F020,0%,3,50 ,,,";
preg_match("/(.*?),(.*?),(.*?),(.*?),(.*?),(.*?)\s+(.*?)\s+(.{4})(.{4}),(.*?),(\d+,\d\d)\s/",
$string, $matches);
var_export ($matches);
This outputs:
array (
0 => 'format,surcharge,amount,1,card,basicprice 3,50 F010F020,0%,3,50 ',
1 => 'format',
2 => 'surcharge',
3 => 'amount',
4 => '1',
5 => 'card',
6 => 'basicprice',
7 => '3,50',
8 => 'F010',
9 => 'F020',
10 => '0%',
11 => '3,50',
)

C128 Barcode script in php

I want to add code 128 auto barcode in codeigniter framework.I used http://davidscotttufts.com/2009/03/31/how-to-create-barcodes-in-php/ for this but it is generating code128B format.I have also used http://www.barcodephp.com/en/download but could not be able to properly add classes in codeigniter framework.Can anyone help me or suggest me code128 auto barcode php script.
Thanks in advance
<?php
// Get thickness parameter from $_GET:
$thickness = ( isset( $_GET["thickness"] ) ? $_GET[ "thickness" ] : 2 );
$text = (isset($_GET["text"])?$_GET["text"]:"00000000024");
//$text=(int)$text;
$size = (isset($_GET["size"])?$_GET["size"]:"30");
$orientation = (isset($_GET["orientation"])?$_GET["orientation"]:"horizontal");
$code_type = (isset($_GET["codetype"])?$_GET["codetype"]:"code128");
$code_string = "";
// Translate the $text into barcode the correct $code_type
if ( strtolower($code_type) == "code128" ) {
$code_array = array(
0 => '11011001100',
1 => '11001101100',
2 => '11001100110',
3 => '10010011000',
4 => '10010001100',
5 => '10001001100',
6 => '10011001000',
7 => '10011000100',
8 => '10001100100',
9 => '11001001000',
10 => '11001000100',
11 => '11000100100',
12 => '10110011100',
13 => '10011011100',
14 => '10011001110',
15 => '10111001100',
16 => '10011101100',
17 => '10011100110',
18 => '11001110010',
19 => '11001011100',
20 => '11001001110',
21 => '11011100100',
22 => '11001110100',
23 => '11101101110',
24 => '11101001100',
25 => '11100101100',
26 => '11100100110',
27 => '11101100100',
28 => '11100110100',
29 => '11100110010',
30 => '11011011000',
31 => '11011000110',
32 => '11000110110',
33 => '10100011000',
34 => '10001011000',
35 => '10001000110',
36 => '10110001000',
37 => '10001101000',
38 => '10001100010',
39 => '11010001000',
40 => '11000101000',
41 => '11000100010',
42 => '10110111000',
43 => '10110001110',
44 => '10001101110',
45 => '10111011000',
46 => '10111000110',
47 => '10001110110',
48 => '11101110110',
49 => '11010001110',
50 => '11000101110',
51 => '11011101000',
52 => '11011100010',
53 => '11011101110',
54 => '11101011000',
55 => '11101000110',
56 => '11100010110',
57 => '11101101000',
58 => '11101100010',
59 => '11100011010',
60 => '11101111010',
61 => '11001000010',
62 => '11110001010',
63 => '10100110000',
64 => '10100001100',
65 => '10010110000',
66 => '10010000110',
67 => '10000101100',
68 => '10000100110',
69 => '10110010000',
70 => '10110000100',
71 => '10011010000',
72 => '10011000010',
73 => '10000110100',
74 => '10000110010',
75 => '11000010010',
76 => '11001010000',
77 => '11110111010',
78 => '11000010100',
79 => '10001111010',
80 => '10100111100',
81 => '10010111100',
82 => '10010011110',
83 => '10111100100',
84 => '10011110100',
85 => '10011110010',
86 => '11110100100',
87 => '11110010100',
88 => '11110010010',
89 => '11011011110',
90 => '11011110110',
91 => '11110110110',
92 => '10101111000',
93 => '10100011110',
94 => '10001011110',
95 => '10111101000',
96 => '10111100010',
97 => '11110101000',
98 => '11110100010',
99 => '10111011110',
100 => '10111101110',
101 => '11101011110',
102 => '11110101110',
'c' => '10111011110',
'b' => '10111101110',
'a' => '11101011110',
'A' => '11010000100',
'B' => '11010010000',
'C' => '11010011100',
'S' => '1100011101011'
);
$code = array();
$strCode;
// settype($code,'string');
//$this->sourceCode = $code;
$nbKr = strlen($code);
$strCode = '';
for( $i=0; $i<$nbKr; $i++ ) {
$code[$i] = substr($code, $i, 1);
}
$strCode = $code_array['B']; // Start
$checksum = 104 ;
$j = 1 ;
for( $i=0; $i<$nbKr; $i++ ) {
$tmp = ord($code[$i]) - 32 ;
$checksum += ( $j++ * $tmp ) ;
$strCode .= $code_array[$tmp];
}
$checksum %= 103 ;
$strCode .= $code_array[$checksum];
$strCode .= $code_array['S']; // Stop
$strCode = $strCode;
$tmp = strlen($strCode) + 20;
$width = $tmp;
}
// Pad the edges of the barcode
$code_length = 20;
for ( $i=1; $i <= strlen($code_string); $i++ )
$code_length = $code_length + (integer)(substr($code_string,($i-1),1));
if ( strtolower($orientation) == "horizontal" ) {
//$img_width = $code_length;
$img_width = $code_length * $thickness;
$img_height = $size;
} else {
$img_width = $size;
$img_height = $code_length;
}
$image = imagecreate($img_width, $img_height);
$black = imagecolorallocate ($image, 0, 0, 0);
$white = imagecolorallocate ($image, 255, 255, 255);
imagefill( $image, 0, 0, $white );
//$location = 10;
$location = 10 * $thickness;
for ( $position = 1 ; $position <= strlen($code_string); $position++ ) {
//$cur_size = $location + ( substr($code_string, ($position-1), 1);
$cur_size = $location + ( substr($code_string, ($position-1), 1) *$thickness);
if ( strtolower($orientation) == "horizontal" )
imagefilledrectangle( $image, $location, 0, $cur_size, $img_height, ($position % 2 == 0 ? $white : $black) );
else
imagefilledrectangle( $image, 0, $location, $img_width, $cur_size, ($position % 2 == 0 ? $white : $black) );
$location = $cur_size;
}
// Draw barcode to the screen
header ('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>
You can actually follow the examples at https://github.com/tecnickcom/tc-lib-barcode/blob/develop/example/index.php
For example:
$bobj = $barcode->getBarcodeObj('QRCODE,H', 'hello world', -4, -4, 'black');
echo "<img alt=\"Embedded Image\" src=\"data:image/png;base64,".base64_encode($bobj->getPngData())."\" />";
or if you want to print the barcode in a different format:
echo $bobj->getHtmlDiv();
The examples uses the tc-lib-barcode (https://github.com/tecnickcom/tc-lib-barcode) PHP Software library to generate both linear and bidimensional barcodes.
The source code is fully PSR-2 compliant and can be easily added to your PHP projects using Composer.
The original code has been ported and refactored from TCPDF and already used in billions of documents.

PHP FFT module error

I wrote a FFT (Fast Fourier Transform) module for PHP recently. When I tried to test it, It always throws an error that the array $this->reverseTable has some index not defined. I got no clue of how to solve this problem.
Here's the PHP code:
<?php
class FourierTransform {
public $bufferSize;
public $sampleRate;
public $bandwidth;
public $spectrum = array();
public $real = array();
public $imag = array();
public $peakBand = 0;
public $peak = 0;
public function __construct($bufferSize,$sampleRate){
$this->bufferSize = $bufferSize;
$this->sampleRate = $sampleRate;
$this->bandwidth = 2 / $bufferSize * $sampleRate / 2;
}
public function getBandFrequency($index){
return $this->bandwidth * $index + $this->bandwidth / 2;
}
public function calculateSpectrum(){
$bSi = 2 / $this->bufferSize;
for($i = 0,$N = $this->bufferSize/2; $i < $N; $i++){
$rval = $this->real[$i];
$ival = $this->imag[$i];
$mag = $bSi * sqrt($rval * $rval + $ival * $ival);
if($mag > $this->peak){
$this->peakBand = $i;
$this->peak = $mag;
}
$this->spectrum[$i] = $mag;
}
}
}
class FFT extends FourierTransform {
public $reverseTable = array();
public $sinTable = array();
public $cosTable = array();
public function __construct($bufferSize,$sampleRate){
parent::__construct($bufferSize,$sampleRate);
$limit = 1;
$bit = $bufferSize >> 1;
while($limit < $bufferSize){
for($i = 0; $i < $limit; $i++){
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
}
$limit = $limit << 1;
$bit = $bit >> 1;
}
for($i = 0; $i < $bufferSize; $i++){
$this->sinTable[$i] = sin(-M_PI / $i);
$this->cosTable[$i] = cos(-M_PI / $i);
}
}
public function foward($buffer){
$k = floor(log($this->bufferSize,2));
if(pow(2,$k) !== $this->bufferSize) throw new Exception('Invalid buffer size, must be a power of 2.');
if($this->bufferSize !== count($buffer)) throw new Exception('Supplied buffer is not the same size as defined FFT.');
$halfSize = 1;
for($i = 0; $i < $this->bufferSize; $i++){
$this->real[$i] = $buffer[$this->reverseTable[$i]];
$this->imag[$i] = 0;
}
while($halfSize < $this->bufferSize){
$phaseShiftReal = $this->cosTable[$halfSize];
$phaseShiftImag = $this->sinTable[$halfSize];
$currentPhaseShiftReal = 1;
$currentPhaseShiftImag = 0;
for($fftStep = 0; $fftStep < $halfSize; $fftStep++){
while($fftStep < $this->bufferSize){
$off = $fftStep + $halfSize;
$tr = ($currentPhaseShiftReal * $this->real[$off]) - ($currentPhaseShiftImag * $this->imag[$off]);
$ti = ($currentPhaseShiftReal * $this->imag[$off]) + ($currentPhaseShiftImag * $this->real[$off]);
$this->real[$off] = $this->real[$fftStep] - $tr;
$this->imag[$off] = $this->imag[$fftStep] - $ti;
$this->real[$fftStep] += $tr;
$this->imag[$fftStep] += $ti;
$fftStep += $halfSize << 1;
}
$tmpReal = $currentPhaseShiftReal;
$currentPhaseShiftReal = ($tmpReal * $phaseShiftReal) - ($currentPhaseShiftImag * $phaseShiftImag);
$currentPhaseShiftImag = ($tmpReal * $phaseShiftImag) + ($currentPhaseShiftImag * $phaseShiftReal);
}
$halfSize = $halfSize << 1;
}
$this->calculateSpectrum();
}
}
?>
The test sample is a sine wave at 440Hz.
When I tried to run the code, it throws this error
Notice: Undefined offset: 0 in C:\Program Files
(x86)\EasyPHP-12.1\www\fft.php on line 48
continuously.
The array that has problem has data like this:
Array
(
[1] => 512
[2] => 256
[3] => 768
[4] => 128
[5] => 640
[6] => 384
[7] => 896
[8] => 64
[9] => 576
[10] => 320
[11] => 832
[12] => 192
[13] => 704
[14] => 448
[15] => 960
[16] => 32
[17] => 544
[18] => 288
[19] => 800
[20] => 160
[21] => 672
[22] => 416
[23] => 928
[24] => 96
[25] => 608
[26] => 352
[27] => 864
[28] => 224
[29] => 736
[30] => 480
[31] => 992
[32] => 16
[33] => 528
[34] => 272
[35] => 784
[36] => 144
[37] => 656
[38] => 400
[39] => 912
[40] => 80
[41] => 592
[42] => 336
[43] => 848
[44] => 208
[45] => 720
...
[978] => 303
[979] => 815
[980] => 175
[981] => 687
[982] => 431
[983] => 943
[984] => 111
[985] => 623
[986] => 367
[987] => 879
[988] => 239
[989] => 751
[990] => 495
[991] => 1007
[992] => 31
[993] => 543
[994] => 287
[995] => 799
[996] => 159
[997] => 671
[998] => 415
[999] => 927
[1000] => 95
[1001] => 607
[1002] => 351
[1003] => 863
[1004] => 223
[1005] => 735
[1006] => 479
[1007] => 991
[1008] => 63
[1009] => 575
[1010] => 319
[1011] => 831
[1012] => 191
[1013] => 703
[1014] => 447
[1015] => 959
[1016] => 127
[1017] => 639
[1018] => 383
[1019] => 895
[1020] => 255
[1021] => 767
[1022] => 511
[1023] => 1023
)
Edit: The previous problem is solved but now another problem is raised. At function forward() it throws an uncaught exception Invalid buffer size, must be a power of 2. Even if the buffer size is right.
Any help will be appreciated.
Assuming that this is the whole class, I presume that the issue lies on this line inside your FFT constructor:
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
From what I can tell you declare reverseTable as an array, but this line is the only place in the class where any elements are added to that array, so the fact that you're setting the reverseTable[$i+$limit] element using a never-defined reverseTable[$i] value is going to give you problems in the first first iteration of that while loop when it tries to use the undefined index $i (reverseTable[$i]). You'll have to give reverseTable[0] a value before you enter that loop.
Although you didn't provide where the line was, my guess is it has something to do with this line:
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
This is in your constructor, and this bit especially looks wrong $this->reverseTable[$i] + $bit;. You are asking for the value from the reverseTable array, but this key is not initialized anywhere in the constructor.
I am not sure how to fix this, as it is a logic error on your part.

Converting a One-Dimensional Array into a Nested Array Using Relationship Keys

Say I have an array with keys representing id and values representing parent:
4 => 0
2 => 0
5 => 2
6 => 5
8 => 0
9 => 0
10 => 8
12 => 0
13 => 0
14 => 0
18 => 7
19 => 18
20 => 19
21 => 20
22 => 21
23 => 22
24 => 23
28 => 20
7 => 5
You could also read this as an object:
{
id : 4,
parent : 0
} // etc...
The multidimensional array I'd want to achieve from this would be:
4 => 0
2 => 5
=> 6
=> 7
=> 18
=> 19
=> 20
=> 21
=> 22
=> 23
=> 24
=> 28
8 => 10
9 => 0
12 => 0
13 => 0
14 => 0
How would I go about doing this?
If you write a little helper function to rework your data to a structure similar to:
$input = array(
array('id' => '4', 'parent' => '0'),
// ...
);
which could be achieved with something like:
$data = array_map(function ($entry) {
list($id, $parent) = array_map('trim', explode('=>', $entry));
return array(
'id' => $id,
'parent' => $parent
);
}, explode("\n", $data));
you could then use a function I used in a similar question:
function flatToNested($d, $r = 0, $p = 'parent', $k = 'id', $c = 'children') {
$m = array();
foreach ($d as $e) {
isset($m[$e[$p]]) ?: $m[$e[$p]] = array();
isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
$m[$e[$p]][] = array_merge($e, array($c => &$m[$e[$k]]));
}
return $m[$r];
}
to produce a nested array with:
$nested = flatToNested($data);
demo: http://codepad.viper-7.com/HAZxaA

PHP: Convert unicode codepoint to UTF-8

I have my data in this format: U+597D or like this U+6211. I want to convert them to UTF-8 (original characters are 好 and 我). How can I do it?
$utf8string = html_entity_decode(preg_replace("/U\+([0-9A-F]{4})/", "&#x\\1;", $string), ENT_NOQUOTES, 'UTF-8');
is probably the simplest solution.
function utf8($num)
{
if($num<=0x7F) return chr($num);
if($num<=0x7FF) return chr(($num>>6)+192).chr(($num&63)+128);
if($num<=0xFFFF) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
if($num<=0x1FFFFF) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128);
return '';
}
function uniord($c)
{
$ord0 = ord($c{0}); if ($ord0>=0 && $ord0<=127) return $ord0;
$ord1 = ord($c{1}); if ($ord0>=192 && $ord0<=223) return ($ord0-192)*64 + ($ord1-128);
$ord2 = ord($c{2}); if ($ord0>=224 && $ord0<=239) return ($ord0-224)*4096 + ($ord1-128)*64 + ($ord2-128);
$ord3 = ord($c{3}); if ($ord0>=240 && $ord0<=247) return ($ord0-240)*262144 + ($ord1-128)*4096 + ($ord2-128)*64 + ($ord3-128);
return false;
}
utf8() and uniord() try to mirror the chr() and ord() functions on php:
echo utf8(0x6211)."\n";
echo uniord(utf8(0x6211))."\n";
echo "U+".dechex(uniord(utf8(0x6211)))."\n";
//In your case:
$wo='U+6211';
$hao='U+597D';
echo utf8(hexdec(str_replace("U+","", $wo)))."\n";
echo utf8(hexdec(str_replace("U+","", $hao)))."\n";
output:
我
25105
U+6211
我
好
PHP 7+
As of PHP 7, you can use the Unicode codepoint escape syntax to do this.
echo "\u{597D}"; outputs 好.
I just wrote a polyfill for missing multibyte versions of ord and chr with the following in mind:
It defines functions mb_ord and mb_chr only if they don't already exist. If they do exist in your framework or some future version of PHP, the polyfill will be ignored.
It uses the widely used mbstring extension to do the conversion. If the mbstring extension is not loaded, it will use the iconv extension instead.
I also added functions for HTMLentities encoding / decoding and encoding / decoding to JSON format as well as some demo code for how to use these functions
Code
if (!function_exists('codepoint_encode')) {
function codepoint_encode($str) {
return substr(json_encode($str), 1, -1);
}
}
if (!function_exists('codepoint_decode')) {
function codepoint_decode($str) {
return json_decode(sprintf('"%s"', $str));
}
}
if (!function_exists('mb_internal_encoding')) {
function mb_internal_encoding($encoding = NULL) {
return ($from_encoding === NULL) ? iconv_get_encoding() : iconv_set_encoding($encoding);
}
}
if (!function_exists('mb_convert_encoding')) {
function mb_convert_encoding($str, $to_encoding, $from_encoding = NULL) {
return iconv(($from_encoding === NULL) ? mb_internal_encoding() : $from_encoding, $to_encoding, $str);
}
}
if (!function_exists('mb_chr')) {
function mb_chr($ord, $encoding = 'UTF-8') {
if ($encoding === 'UCS-4BE') {
return pack("N", $ord);
} else {
return mb_convert_encoding(mb_chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE');
}
}
}
if (!function_exists('mb_ord')) {
function mb_ord($char, $encoding = 'UTF-8') {
if ($encoding === 'UCS-4BE') {
list(, $ord) = (strlen($char) === 4) ? #unpack('N', $char) : #unpack('n', $char);
return $ord;
} else {
return mb_ord(mb_convert_encoding($char, 'UCS-4BE', $encoding), 'UCS-4BE');
}
}
}
if (!function_exists('mb_htmlentities')) {
function mb_htmlentities($string, $hex = true, $encoding = 'UTF-8') {
return preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function ($match) use ($hex) {
return sprintf($hex ? '&#x%X;' : '&#%d;', mb_ord($match[0]));
}, $string);
}
}
if (!function_exists('mb_html_entity_decode')) {
function mb_html_entity_decode($string, $flags = null, $encoding = 'UTF-8') {
return html_entity_decode($string, ($flags === NULL) ? ENT_COMPAT | ENT_HTML401 : $flags, $encoding);
}
}
How to use
echo "\nGet string from numeric DEC value\n";
var_dump(mb_chr(25105));
var_dump(mb_chr(22909));
echo "\nGet string from numeric HEX value\n";
var_dump(mb_chr(0x6211));
var_dump(mb_chr(0x597D));
echo "\nGet numeric value of character as DEC int\n";
var_dump(mb_ord('我'));
var_dump(mb_ord('好'));
echo "\nGet numeric value of character as HEX string\n";
var_dump(dechex(mb_ord('我')));
var_dump(dechex(mb_ord('好')));
echo "\nEncode / decode to DEC based HTML entities\n";
var_dump(mb_htmlentities('我好', false));
var_dump(mb_html_entity_decode('我好'));
echo "\nEncode / decode to HEX based HTML entities\n";
var_dump(mb_htmlentities('我好'));
var_dump(mb_html_entity_decode('我好'));
echo "\nUse JSON encoding / decoding\n";
var_dump(codepoint_encode("我好"));
var_dump(codepoint_decode('\u6211\u597d'));
Output
Get string from numeric DEC value
string(3) "我"
string(3) "好"
Get string from numeric HEX value
string(3) "我"
string(3) "好"
Get numeric value of character as DEC string
int(25105)
int(22909)
Get numeric value of character as HEX string
string(4) "6211"
string(4) "597d"
Encode / decode to DEC based HTML entities
string(16) "我好"
string(6) "我好"
Encode / decode to HEX based HTML entities
string(16) "我好"
string(6) "我好"
Use JSON encoding / decoding
string(12) "\u6211\u597d"
string(6) "我好"
mb_convert_encoding(
preg_replace("/U\+([0-9A-F]*)/"
,"&#x\\1;"
,'U+597DU+6211'
)
,"UTF-8"
,"HTML-ENTITIES"
);
works fine, too.
<?php
function chr_utf8($n,$f='C*'){
return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n):
($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n):
($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):'')));
}
$your_input='U+597D';
echo (chr_utf8(hexdec(ltrim($your_input,'U+'))));
// Output 好
If you want to use a callback function you can try it :
<?php
// Note: function chr_utf8 shown above is required
$your_input='U+597DU+6211';
$result=preg_replace_callback('#U\+([a-f0-9]+)#i',function($a){return chr_utf8(hexdec($a[1]));},$your_input);
echo $result;
// Output 好我
Check it in https://eval.in/748187
I was in the position I needed to filter specific characters without affecting the html because I was using a wysiwig editor, but people copy pasting from word would add some nice unrenderable characters to the content.
My solution boils down to simple replacement lists.
class ReplaceIllegal {
public static $find = array ( 0 => '\x0', 1 => '\x1', 2 => '\x2', 3 => '\x3', 4 => '\x4', 5 => '\x5', 6 => '\x6', 7 => '\x7', 8 => '\x8', 9 => '\x9', 10 => '\xA', 11 => '\xB', 12 => '\xC', 13 => '\xD', 14 => '\xE', 15 => '\xF', 16 => '\x10', 17 => '\x11', 18 => '\x12', 19 => '\x13', 20 => '\x14', 21 => '\x15', 22 => '\x16', 23 => '\x17', 24 => '\x18', 25 => '\x19', 26 => '\x1A', 27 => '\x1B', 28 => '\x1C', 29 => '\x1D', 30 => '\x1E', 31 => '\x80', 32 => '\x81', 33 => '\x82', 34 => '\x83', 35 => '\x84', 36 => '\x85', 37 => '\x86', 38 => '\x87', 39 => '\x88', 40 => '\x89', 41 => '\x8A', 42 => '\x8B', 43 => '\x8C', 44 => '\x8D', 45 => '\x8E', 46 => '\x8F', 47 => '\x90', 48 => '\x91', 49 => '\x92', 50 => '\x93', 51 => '\x94', 52 => '\x95', 53 => '\x96', 54 => '\x97', 55 => '\x98', 56 => '\x99', 57 => '\x9A', 58 => '\x9B', 59 => '\x9C', 60 => '\x9D', 61 => '\x9E', 62 => '\x9F', 63 => '\xA0', 64 => '\xA1', 65 => '\xA2', 66 => '\xA3', 67 => '\xA4', 68 => '\xA5', 69 => '\xA6', 70 => '\xA7', 71 => '\xA8', 72 => '\xA9', 73 => '\xAA', 74 => '\xAB', 75 => '\xAC', 76 => '\xAD', 77 => '\xAE', 78 => '\xAF', 79 => '\xB0', 80 => '\xB1', 81 => '\xB2', 82 => '\xB3', 83 => '\xB4', 84 => '\xB5', 85 => '\xB6', 86 => '\xB7', 87 => '\xB8', 88 => '\xB9', 89 => '\xBA', 90 => '\xBB', 91 => '\xBC', 92 => '\xBD', 93 => '\xBE', 94 => '\xBF', 95 => '\xC0', 96 => '\xC1', 97 => '\xC2', 98 => '\xC3', 99 => '\xC4', 100 => '\xC5', 101 => '\xC6', 102 => '\xC7', 103 => '\xC8', 104 => '\xC9', 105 => '\xCA', 106 => '\xCB', 107 => '\xCC', 108 => '\xCD', 109 => '\xCE', 110 => '\xCF', 111 => '\xD0', 112 => '\xD1', 113 => '\xD2', 114 => '\xD3', 115 => '\xD4', 116 => '\xD5', 117 => '\xD6', 118 => '\xD7', 119 => '\xD8', 120 => '\xD9', 121 => '\xDA', 122 => '\xDB', 123 => '\xDC', 124 => '\xDD', 125 => '\xDE', 126 => '\xDF', 127 => '\xE0', 128 => '\xE1', 129 => '\xE2', 130 => '\xE3', 131 => '\xE4', 132 => '\xE5', 133 => '\xE6', 134 => '\xE7', 135 => '\xE8', 136 => '\xE9', 137 => '\xEA', 138 => '\xEB', 139 => '\xEC', 140 => '\xED', 141 => '\xEE', 142 => '\xEF', 143 => '\xF0', 144 => '\xF1', 145 => '\xF2', 146 => '\xF3', 147 => '\xF4', 148 => '\xF5', 149 => '\xF6', 150 => '\xF7', 151 => '\xF8', 152 => '\xF9', 153 => '\xFA', 154 => '\xFB', 155 => '\xFC', 156 => '\xFD', 157 => '\xFE', );
private static $replace = array ( 0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => '', 7 => '', 8 => '', 9 => ' ', 10 => '
', 11 => '', 12 => '', 13 => '
', 14 => '', 15 => '', 16 => '', 17 => '', 18 => '', 19 => '', 20 => '', 21 => '', 22 => '', 23 => '', 24 => '', 25 => '', 26 => '', 27 => '', 28 => '', 29 => '', 30 => '', 31 => '€', 32 => '', 33 => '‚', 34 => 'ƒ', 35 => '„', 36 => '…', 37 => '†', 38 => '‡', 39 => 'ˆ', 40 => '‰', 41 => 'Š', 42 => '‹', 43 => 'Œ', 44 => '', 45 => 'Ž', 46 => '', 47 => '', 48 => '‘', 49 => '’', 50 => '“', 51 => '”', 52 => '•', 53 => '–', 54 => '—', 55 => '˜', 56 => '™', 57 => 'š', 58 => '›', 59 => 'œ', 60 => '', 61 => 'ž', 62 => 'Ÿ', 63 => ' ', 64 => '¡', 65 => '¢', 66 => '£', 67 => '¤', 68 => '¥', 69 => '¦', 70 => '§', 71 => '¨', 72 => '©', 73 => 'ª', 74 => '«', 75 => '¬', 76 => '­', 77 => '®', 78 => '¯', 79 => '°', 80 => '±', 81 => '²', 82 => '³', 83 => '´', 84 => 'µ', 85 => '¶', 86 => '·', 87 => '¸', 88 => '¹', 89 => 'º', 90 => '»', 91 => '¼', 92 => '½', 93 => '¾', 94 => '¿', 95 => 'À', 96 => 'Á', 97 => 'Â', 98 => 'Ã', 99 => 'Ä', 100 => 'Å', 101 => 'Æ', 102 => 'Ç', 103 => 'È', 104 => 'É', 105 => 'Ê', 106 => 'Ë', 107 => 'Ì', 108 => 'Í', 109 => 'Î', 110 => 'Ï', 111 => 'Ð', 112 => 'Ñ', 113 => 'Ò', 114 => 'Ó', 115 => 'Ô', 116 => 'Õ', 117 => 'Ö', 118 => '×', 119 => 'Ø', 120 => 'Ù', 121 => 'Ú', 122 => 'Û', 123 => 'Ü', 124 => 'Ý', 125 => 'Þ', 126 => 'ß', 127 => 'à', 128 => 'á', 129 => 'â', 130 => 'ã', 131 => 'ä', 132 => 'å', 133 => 'æ', 134 => 'ç', 135 => 'è', 136 => 'é', 137 => 'ê', 138 => 'ë', 139 => 'ì', 140 => 'í', 141 => 'î', 142 => 'ï', 143 => 'ð', 144 => 'ñ', 145 => 'ò', 146 => 'ó', 147 => 'ô', 148 => 'õ', 149 => 'ö', 150 => '÷', 151 => 'ø', 152 => 'ù', 153 => 'ú', 154 => 'û', 155 => 'ü', 156 => 'ý', 157 => 'þ', );
/*
* replace illegal characters for escaped html character but don't touch anything else.
*/
public static function getSaveValue($value) {
return str_replace(self::$find, self::$replace, $value);
}
public static function makeIllegal($find,$replace) {
self::$find[] = $find;
self::$replace[] = $replace;
}
}
This worked fine for me. If you have a string "Letters u00e1 u00e9 etc." replace by "Letters á é".
function unicode2html($str){
// Set the locale to something that's UTF-8 capable
setlocale(LC_ALL, 'en_US.UTF-8');
// Convert the codepoints to entities
$str = preg_replace("/u([0-9a-fA-F]{4})/", "&#x\\1;", $str);
// Convert the entities to a UTF-8 string
return iconv("UTF-8", "ISO-8859-1//TRANSLIT", $str);
}
With the aid of the following table:
http://en.wikipedia.org/wiki/UTF-8#Description
can't be simpler :)
Simply mask the unicode numbers according to which range they fit in.

Categories