顯示具有 字串對齊 標籤的文章。 顯示所有文章
顯示具有 字串對齊 標籤的文章。 顯示所有文章

2015年7月15日 星期三

多國語言小數點符號處理

撰寫多國語系的軟體,必須注意到一些特殊處理事項
本篇所針對的數值呈現問題,將可能造成很嚴重的後果

首先,先明白數值表示法這件事情,在某些歐洲或美洲、東南亞地區數值的小數點符號,並不是「.」,而是「,」,所以當你的程式輸出檔案或者顯示在主控台的時候,會出現312.566被顯示成312,566 這種情形。如下圖的 fValue




這樣的狀況並不只是看起來怪怪的而已,更嚴重的是,如果你要下SQL指令,而且你的指令並不是透過SqlCommand物件的正規使用方式來進行,而是自己串出SQL指令的話,就會讓指令失敗,由於你的數值如果帶有小數點,會變成逗號,這會讓SQL指令被誤解析。

比方
sb.Append("INSERT INTO TB_RECORD_RAW VALUES (").Append(intIoId).Append(",").Append(douValue).Append(");”).
原本預期輸出
INSERT INTO TB_RECORD_RAW VALUES ( 123, 194.566 );
但結果會輸出
INSERT INTO TB_RECORD_RAW VALUES ( 123, 194,566 );
這會讓SQL誤判有三個參數要Insert,但是實際上只有兩個。結果要不就是填錯欄位,要不就會新增失敗(也許欄位不夠多)。


解決這個問題有兩種方式,要不就是透過SqlCommand物件的正規使用方式來進行。要不就是透過修改數值顯示方式(各國有各種特定的表示方式,可以在程式中強制統一),底下針對修改數值顯示方式來介紹。

CultureInfo TheCulture = new CultureInfo("en-US", false);
NumberFormatInfo NumFmtInf = TheCulture.NumberFormat;
NumFmtInf.NumberDecimalSeparator = ".";
NumFmtInf.NumberDecimalDigits = 10;

Double TestDot_ Double = 123.4567;
String Str_Result = String.Format(TheCulture, "{0:F}", TestDot_Double);

透過CultureInfo所建立的物件,會存放著作業系統的文化語言相關設定,指定為"en-US"是美國 “zh-TW則是台灣所有語言列表於http://www.csharp-examples.net/culture-names/


也可以客制化的修改小數點符號,也可指定浮點數一律顯示到小數點後第幾位,這邊稍微要注意的是,當你在此指定了小數點後第幾位,則不足位數會補零,比方123.4567000000。如果不設定呢,則預設會顯示小數點兩位,進行四捨五入。

2011年9月8日 星期四

字串格式與對齊解說(三)數值篇

String.Format( String, Object )的使用方式有點類似之前C的printf()
舉例來看:

ResultStr = String.Format( "謝謝您在{1:##}分鐘內閱讀本文章第 {0:00###} 次了.",123,60);
ReadAmount = 123;
ResultStr = String.Format( "謝謝您在{1:##}分鐘內閱讀本文章第 {0:00###} 次了.",ReadAmount,60 );
這樣的語法,就能得到 ResultStr = "謝謝您在60分鐘內閱讀本文章第00123次了。也就是說,可以傳入由字串格式項目與參數的組合來達到串出所需字串的目的,而在 { } 兩個大括弧中間的,就是控制格式化的部分,而大刮號之間的第一個數字,是表示要用後面所給的第幾個參數,通常會是需要被格式化的「數字、時間、.....等等格式」,比方,以第二個例子來說,就會拿後面的參數60代到前面的{1}那邊,而參數ReadAmount則是會被代到前面的{0}的地方而 : 符號後面的部分,則是可以用很複雜的控制代碼,控制代碼,分成很多種。

我們先看常用的標準的格式代碼(格式碼通常不用在意大小寫,都適用)
----------------------------------------------------------------------------------------------
C 表示貨幣,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前NumberFormatInfo物件所提供的預設貨幣精確度。 
例如:String.Format( "{0:C5}", 12345.678901234 )則會得到NT$12,345.67890  
 
D 表示十進位(只支援整數型別),並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零
例如:String.Format( "{0:D8}", 12345 )則會得到00012345 
 
E 表示科學符號,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
例如:String.Format( "{0:E}", 12345.678901234 )則會得到1.234568E+004
 

F 表示浮點數,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
例如:String.Format( "{0:F3}", 12345.678901234 )則會得到12345.679
 

G 表示一般,並且可接著一個數字,來並且可接著一個數字,來表示要顯示多少位數(包含整數與小數的部分),而可能轉為科學記號,也可能轉出浮點數,(說明文件說會挑以最精簡顯示方式來顯示,但很難懂),直接看範例
例如:String.Format( "{0:G3}", 12345.678901234 )則會得到123e+04
例如:String.Format( "{0:G4}", 12345.678901234 )則會得到1235e+04
例如:String.Format( "{0:G5}", 12345.678901234 )則會得到12346
例如:String.Format( "{0:G6}", 12345.678901234 )則會得到12345.7


N 表示數字,並且可接著一個數字,表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
例如:String.Format( "{0:N3}", 12345.678901234 )則會得到12345.679
 

P 表示百分比,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
例如:String.Format( "{0:E}", 12345.678901234 )則會得到1.234568E+004
 

X 表示16進位,並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零。這個X的大小寫,有意義,會指定輸出的16進位的英文部分要大寫還是小寫。
例如:String.Format( "{0:X8}", 123456 )則會得到0001E240



我們再看常用的自訂的格式代碼
----------------------------------------------------------------------------------------------
0 的用法是會讓轉出來的字串被數字取代,但是如果沒數字的地方,會補零。
# 的用法是會讓轉出來的字串被數字取代,但是如果沒數字的地方,不會有數字。
. 的用法是決定轉出的字串的小數點對齊位置。
\ 的用法是讓這些保留控制碼也可以被顯示出來。
其他符號都會直接被顯示在轉出的字串裡


例如:
String.Format( "{0:000000}", 1234 )則會得到001234
String.Format( "{0:000.000}", 1234.56 )則會得到1234.560
String.Format( "{0:######}", 1234.56 )則會得到1234
String.Format( "{0:###.###}", 1234.56 )則會得到1234.56
String.Format( "{0:###.000}", 1234.56 )則會得到1234.560




補充PadLft與PadRight

字串格式與對齊解說(二)時間篇


標準的日期時間格式如下表


格式
說明
指令
輸出
"d"
簡短日期模式。
String.Format( "{0:d}", TheDateTime );
2009/6/15
"D"
完整日期模式。
String.Format( "{0:D}", TheDateTime );
2009615
"f"
完整日期/時間模式 (簡短時間)
String.Format( "{0:f}", TheDateTime );
2009615 下午 01:45
"F"
完整日期/時間模式 (完整時間)
String.Format( "{0:F}", TheDateTime );
2009615 下午 01:45:30
"g"
一般日期/時間模式 (簡短時間)
String.Format( "{0:g}", TheDateTime );
2009/6/15 下午 01:45
"G"
一般日期/時間模式 (完整時間)
String.Format( "{0:G}", TheDateTime );
2009/6/15 下午 01:45:30
"M""m"
/日模式。
String.Format( "{0:m}", TheDateTime );
615
"O""o"
來回日期/時間模式。
String.Format( "{0:o}", TheDateTime );
2009-06-15T13:45:30.0000000
"R"”r"
RFC1123 模式。
String.Format( "{0:r}", TheDateTime );
Mon, 15 Jun 2009 13:45:30 GMT
"s"
可排序日期/時間模式。
String.Format( "{0:s}", TheDateTime );
2009-06-15T13:45:30
"t"
簡短時間模式。
String.Format( "{0:t}", TheDateTime );
下午 01:45
"T"
完整時間模式。
String.Format( "{0:T}", TheDateTime );
下午 01:45:30
"u"
國際可排序日期/時間模式。
String.Format( "{0:u}", TheDateTime );
2009-06-15 13:45:30Z
"U"
國際完整日期/時間模式。
String.Format( "{0:U}", TheDateTime );
2009615 上午 05:45:30
"Y""y"
年月模式。
String.Format( "{0:y}", TheDateTime );
20096



自訂的日期格式時間如下

格式規範
說明
指令
輸出
"d"
月份的日期,從 1 31
Console.WriteLine( String.Format( "{0:d }", dd ) );
15
"dd"
月份的日期,從 01 31
Console.WriteLine( String.Format( "{0:dd }", dd ) );
15
"ddd"
一週中星期幾的縮寫名稱。
Console.WriteLine( String.Format( "{0:ddd }", dd ) );
星期一
"dddd"
一週中星期幾的完整名稱。
Console.WriteLine( String.Format( "{0:dddd }", dd ) );
星期一
"f"
日期和時間值中的秒數小數點後一位。
Console.WriteLine( String.Format( "{0:f }", dd ) );
0
"ff"
日期和時間值中的秒數小數點後兩位。
Console.WriteLine( String.Format( "{0:ff }", dd ) );
00
"fff"
日期和時間值中的秒數小數點後三位。
Console.WriteLine( String.Format( "{0:fff }", dd ) );
000
"ffff"
日期和時間值中的秒數小數點後四位。
Console.WriteLine( String.Format( "{0:ffff }", dd ) );
0001
"fffff"
日期和時間值中的秒數小數點後五位。
Console.WriteLine( String.Format( "{0:fffff }", dd ) );
00012
"ffffff"
日期和時間值中的秒數小數點後六位。
Console.WriteLine( String.Format( "{0:ffffff }", dd ) );
000123
"fffffff"
日期和時間值中的秒數小數點後七位。
Console.WriteLine( String.Format( "{0:fffffff }", dd ) );
0001234
"F"
日期和時間值中的秒數小數點後一位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:F }", dd ) );
"FF"
日期和時間值中的秒數小數點後兩位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FF }", dd ) );
"FFF"
日期和時間值中的秒數小數點後三位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFF}", dd ) );
"FFFF"
日期和時間值中的秒數小數點後四位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFF }", dd ) );
0001
"FFFFF"
日期和時間值中的秒數小數點後五位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFFF }", dd ) );
00012
"FFFFFF"
日期和時間值中的秒數小數點後六位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFFFF }", dd ) );
000123
"FFFFFFF"
日期和時間值中的秒數小數點後七位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFFFFF }", dd ) );
0001234
"g""gg"
時期或時代。
Console.WriteLine( String.Format( "{0:g }", dd ) );
西元
"h"
小時,使用從 0 11 12 小時制。
Console.WriteLine( String.Format( "{0:h }", dd ) );
1
"hh"
小時,使用從 00 11 12 小時制。
Console.WriteLine( String.Format( "{0:hh }", dd ) );
01
"H"
小時,使用從 0 23 24 小時制。
Console.WriteLine( String.Format( "{0:H }", dd ) );
1
"HH"
小時,使用從 00 23 24 小時制。
Console.WriteLine( String.Format( "{0:HH }", dd ) );
01
"K"
時區資訊。
Console.WriteLine( String.Format( "{0:k }", dd ) );
k
"m"
分鐘,從 0 59
Console.WriteLine( String.Format( "{0:m }", dd ) );
8
"mm"
分鐘,從 00 59
Console.WriteLine( String.Format( "{0:mm }", dd ) );
08
"M"
月份,從 1 12
Console.WriteLine( String.Format( "{0:M }", dd ) );
6
"MM"
月份,從 01 12
Console.WriteLine( String.Format( "{0:MM }", dd ) );
06
"MMM"
月份的縮寫名稱。
Console.WriteLine( String.Format( "{0:MMM }", dd ) );
六月
"MMMM"
月份的完整名稱。
Console.WriteLine( String.Format( "{0:MMMM }", dd ) );
六月
"s"
秒數,從 0 59
Console.WriteLine( String.Format( "{0:s }", dd ) );
9
"ss"
秒數,從 00 59
Console.WriteLine( String.Format( "{0:ss }", dd ) );
09
"t"
AM/PM 指示項的第一個字元。
Console.WriteLine( String.Format( "{0:t }", dd ) );
"tt"
AM/PM 指示項。
Console.WriteLine( String.Format( "{0:tt }", dd ) );
上午
"y"
年份,從 0 99
Console.WriteLine( String.Format( "{0:y }", dd ) );
9
"yy"
年份,從 00 99
Console.WriteLine( String.Format( "{0:yy }", dd ) );
09
"yyy"
年份,至少有三位數。
Console.WriteLine( String.Format( "{0:yyy }", dd ) );
2009
"yyyy"
年份,四位數的數字。
Console.WriteLine( String.Format( "{0:yyyy }", dd ) );
2009
"yyyyy"
年份,五位數的數字。
Console.WriteLine( String.Format( "{0:yyyyy }", dd ) );
02009
"z"
UTC 之間的小時時差,若前置字元為零則去掉該字元。
Console.WriteLine( String.Format( "{0:z }", dd ) );
+8
"zz"
UTC 之間的小時時差,若差異值為個位數則前置字元為零。
Console.WriteLine( String.Format( "{0:zz }", dd ) );
+08
"zzz"
UTC 之間的小時和分鐘時差。
Console.WriteLine( String.Format( "{0:zzz }", dd ) );
+08:00