PHP如何正確計算中文字串的長度

  在PHP程式設計中,我們常常遇到需要計算字串長度的場景。一般情況下,我們習慣用 strlen() 函數或 mb_strlen() 函數來計算字串長度。然而,在處理中文字串時,我們會發現使用 strlen() 函數會出現問題,因為中文字元不按照一般的字元計算方式來計算長度。那麼在PHP中,如何才能正確計算中文字串的長度呢?下面就來探討一下相關的問題。
一、PHP中字串長度的計算方式
在PHP中,計算字串長度的方式有兩種,一種是簡單的字元計數,另一種是按照實際字元長度計算。在計算字串長度時,我們會遇到兩種情況:
1.ASCII字元:在計算ASCII字元的長度時,直接使用 strlen() 函數即可。
2.中文字元:中文字元在Unicode佔用兩個字節,而在GBK中佔用兩個位元組或三個位元組。在計算中文字元長度時,需要按照字元的實際長度來計算。

二、誤用strlen() 函數的問題
strlen() 函數是PHP中一個用來計算字串長度的基本函數,它可以傳回指定字串的長度。然而,在處理中文字串時,使用 strlen() 函數會出現問題,計算長度不準確。這是由於 PHP 預設採用 ASCII 編碼,而對於 Unicode 編碼的中文字符,一個字元被解析成多個字節,導致計算長度時發生錯誤。

三、解決問題的方法
既然 strlen() 函數無法正常計算中文字元的長度,那麼我們該如何計算中文字元的長度呢?以下就是三種常用的解決方案:

1.使用 mb_strlen() 函數
PHP提供了 mb_strlen() 函數來解決字串長度問題。 mb_strlen() 函數是一個多位元組字串長度函數,它可以傳回字串的實際長度,包括中文字元在內。使用mb_strlen() 函數計算中文字串的長度時,需要傳入第二個參數來指定字元編碼,例如:
$my_str="不要在你的智慧中夾雜著傲慢。不要使你的謙虛新缺乏智慧。";
$len=mb_strlen($my_str,'utf-8'); // len=27

2.使用iconv_strlen()函數
iconv_strlen() 函數可以用來計算字串的長度,它也可以正確處理中文字串的長度。 iconv_strlen() 函數結構類似strlen() 函數,只不過在計算長度時需要傳入第二個參數指定字元編碼,例如:
$my_str="不要在你的智慧中夾雜著傲慢。不要使你的謙虛新缺乏智慧。";
$len=iconv_strlen($my_str,'utf-8'); // len=27

3.計算位元組數再除以2 或3
除了使用PHP自帶的函數來處理之外,我們還可以透過計算中文字元的位元組數來解決長度計算問題。

把中文英文字串切成陣列-通用的方法

function mb_str_split($str){
	
	return preg_split('/(?<!^)(?!$)/u',$str);
}

圖說演算法使用JavaScript(一)

演算法特性內容與說明
輸入 Input0個或多個輸入資料,這些輸入必須有清楚的描述或定義。
輸出 Output至少會有一個輸出’結果,不可以沒有輸出結果。
明確性 Definiteness每一個指令會步驟必須是簡潔明確而不含糊的。
有限性 Finiteness在有限步驟後一定會結束,不會產生無窮迴路。
有效性 Effectiveness步驟清楚且可行,能讓使用者用紙筆計算而求出答案。
執行Node.js
再命令提示字元下輸入Node即可執行。

地球上最常見經典演算法

分治演算法

分治法Divide and conquer是一種很重要的演算法,我們可以應用分治法來逐一拆解複雜的問題,核心精神是將一個難以解決的大問題依照不同的概念,分割成兩個或更多的子問題,以便各個擊破,分而治之。
範例:  
如果有8張很難畫的圖,我們可以分成2組各四幅來完成,如果還是覺得太複雜,繼續再分成四組,每組各兩幅來完成,利用相同模式反覆切割問題,這就是最簡單的分治法核心精神。

遞迴演算法

遞迴是種很特殊的演算法,分治法和遞迴法很像,都是將一個複雜的演算法問題的規模變得越來越小,最終使子問題容易求解。
從程式語言的角度來說,遞迴的定義是,假如一個函數或副程式,是由自身所定義或呼叫,就稱為遞迴Recursion,它至少要定義2種條件,一個可以反覆執行的遞迴過程,與一個跳出執行過程的出口。
範例: recursion.js,recursion.php
我們知道階乘函數是數學上有名的函數,對遞迴式而言,也可以看成是很典型的範例,我們一般以符號"!"來表示階乘。如4階乘可寫為4!。
n!=n*(n-1)*(n-2).....*1

JS 範例    recursion.htm

let i=5;
		//var ans;
		function factorial(i) {
			var ans;
			if (i==0) return 1
			else ans=i*factorial(i-1);
			return ans;
		}


	console.log(`${i}階乘值為`+factorial(i));

PHP   範例        recursion.php

<?php
$count_num=5;

function factorial($i){

	if ($i==0) {
		$ans=1;
	}
	else{
		$ans=$i*factorial($i-1);
	}
    return $ans;
}

$result=factorial($count_num);
echo "count_num".$result;
?>

貪心法(給我最好,其餘免談)

貪心法Greed Method又稱為貪婪演算法,分法是從某一起點開始,在每一個解決問題步驟使用貪心原則,都採取在當前狀態下最有利或最優化的選擇,不斷的改進該解答,持續在每一步驟中選擇最佳的方法,並且逐步逼近給並的目標,當達到某一步驟不能再繼續前進時,演算法停止,以盡可能快的求得共好的解。

動態規劃演算表(分治法的麻吉兄弟)

動態規劃法Dynamic Programming Algorithm ,DPA 類似分治法,由20世紀50年代初美國數學家R.E.Bellman所發明,用來研究多階段決策過程的優化過程與求得一個問題的最佳解。動態規劃法主要的做法是如果一個問題答案與子問題
相關的話,就能將大問題拆解成各個小問題,其中與分治法最大不同的地方是可以讓每一個子問題的答案被儲存起來,以供下次求解時直接取用。這樣的作法不但能減少再次需要計算的時間,並將這些解組合成大問題的解答,故使用動態規劃則可以解決重複計算的缺點。

疊代演算法(不斷繞圈的演算法)

疊代法iterative method 是無法使用一次求解,而須反覆運算,例如用迴圈去循環重複程式碼的某些部份來得到答案。
fac.js;fac.php > 請利用for迴圈設計一個計算1!~n!的遞迴程式

fac.js => 不能執行因為我的環境沒有安裝prompt套件

PHP 範例       fac.php

<?
$fac = 1;
$my_n = 10;
for ($i=0; $i<=$my_n; $i++){

	for ($j=$i; $j>0; $j--){
		$fac *=$j;     // $fac=$fac*$j
	} 
	echo $i."!=".$fac."<br>";
	$fac = 1;   //$fac要歸1
}
?>

While迴圈  需要具備三個條件

1.變數初始值
2.迴圈條件式
3.調整變數增減值
<?php
$i = 1;                   //變數初始值
while ($i<10){            //迴圈條件式
	echo $i."<br>";
    	$i +=1;           //調整變數增減值
}   
?>

枚舉演算法(人人都有份的演算法) Enumerate

枚舉法(又稱窮舉法),是一種常見的數學方法,也是日常中使用到最多的一個演算法,它的核心思想就是:枚舉所有的可能。根據問題要求,一一枚舉問題的解答,或者為了解決問題而分為不重複、不遺漏的有限種情況,一一枚舉並加以解決,最終達到解決整個問題的目的。枚舉法這種分析問題、解決問題的方法,得到的結果總是正確,唯一的缺點就是速度太慢。
範例:
當某數1000,依次減去1,2,3...直到哪一數時,相減的結果開始為負數。

JS enumerate.js

<script type="text/javascript">
		x=1;
		num=1000;
		while (num >=0){
			num-=x;
			x=x+1;
		}

		console.log(x-1);
</script>

PHP       enumerate.php

$x=1;

$my_num=1000;
$j = $my_num;
while ($j >=0){

	$j -=$x;
	$x = $x+1;
}

$y=$x-1;
echo $my_num."減到數字".$y."會開始是負數";

波蘭麵種(Poolish)麵包

參考資料

波蘭種(Poolish)=液種
澎澎地如同海綿般的質地,
含水量高, 也可稱之為液種

先製作波蘭種|比例 1:1:0.2

從預計使用的總麵粉量,先取出約30%
以麵粉:水:速發酵母
=1:1:0.2 的比例製作
p.s. 因為長時間發酵,
速發酵母甚至可用更低比例(0.08~0.1%)製作
也可依照當天氣溫調整使用量
極少用量的速酵就足夠了唷!
B. 主麵團:
麵粉=500-150=350g
水=350-150=200g
速發酵母=5-0.3=4.7g
鹽巴=9g

波蘭種發酵|常溫or冷藏

可選擇以下兩種方式進行發酵:
<1> 當日常溫發酵法:
室溫25~27℃, 發酵約8~10個小時
<2> 隔夜冷藏發酵法:
在室溫26℃左右發酵1~2小時後放入冰箱4℃冷藏室繼續冷藏發酵約12~17小時
20250216第一次做歐式麵包
烘烤:
溫度215度烤30分鐘
20250218
烘烤:
加蓋子、蒸氣200度烤30分鐘、再開蓋215度烤20分鐘