2009-05-22 8 views
4

.NETで少し問題があり、小数点タイプで作業しています。次の点を考慮し、念頭に置いて.NETで小数点以下の型を扱うときの問題

<globalization culture="auto" enableClientBasedCulture="true"/> 

:私のWebアプリケーションでは、次のグローバリゼーション設定を使用して小数値123.00はGBPで£123.00、およびEUR 123,00を(カンマに注意してください)となります。私が問題を抱えているのは、123,000(EUR)の小数点からGBPに戻って、123,000になりたいときです。これは大きな問題です。

この場合、私のアプリケーションは、検出されたカルチャに基づいてルックアップテーブルを調べ、その通貨で価格を表示します。この問題は、ユーザーが選択を行い、支払いゲートウェイに送信するためのデータが用意されている場合にのみ発生し、EUR 123,00は123,000になります。

どのように私はこれを克服できますか?

+0

これまでのおかげで皆さん、私はまだどこにでもいません。私は実験を続行し、進捗状況を発表します。 – Richard

+0

まだ進歩はありません。私はユーザーカルチャーに依存したフォーマット番号を表示する必要がありますが、en-GBフォーマットで数字を格納することができなければなりません。 "123.00" =£123.00、€123,00 = 123.00 * NOT "* 123000" NumberInfoクラスによってen-GBとしてフォーマットされたときのユーロ値123,00の値。 – Richard

答えて

1

感謝を。

独自のDecimal値を保持するためのカスタムタイプ/構造を実装することは、実際には私の後ろではなく、必要な機能を実際には与えませんでした(10進数値を適切な現地通貨/フォーマット、私はちょうど必要に応じてそれらを英国のフォーマットに戻すことができませんでした)。 、=「自動」.NETは方法によって、偶然(ブラウザによって提供される値に応じてロケールを設定することを可能にした

<globalization culture="auto" enableClientBasedCulture="true"/> 

設定培養:

問題は、ウェブの設定で、このラインでした'enableClientBasedCulture'はMSDNによれば実装されていないので、省略することができます)。したがって、フランスからの訪問者(ブラウザで言語 'fr-FR'が設定されている)がサイトを訪問した場合、数字の書式はすべて正しく機能します(正しい小数点記号と通貨記号)。それをヨーロッパのフォーマットからイギリス/米国のフォーマットに変換する必要があります。

フランス語ロケールでは "123.00"が有効ではないため、 "123.00"から "fr-FR"ロケールに変換するとFormatExceptionが生成されます( "123,00"が必要です)。しかし、 "123,00"(fr-FR)を英国/米国 'en-GB'または 'en-US'形式に変換してもエラーは発生しませんが、値は「123,000」になります。別のゼロを追加することはできないので、これはFormatExceptionをスローする必要があります。文化へ

  1. 設定文化= "auto" を= "-GBエン" web.configファイルに次のように私は実装

    ソリューションでした。

  2. Decimal.ToString( "c"、ni)を使用します。ここで、 'ni'はカスタムのNumberFormatInfoクラスです。

私の既存のコードは、国に依存し、正しい小数点値を取得するために、我々のデータソースに接続しているので、私は今、持っていたすべての書式設定の問題でした。だから、「FR-FR」ロケールに応じた数をフォーマットするために、あなたが行うことができます。この設定で

NumberFormatInfo ni = Globalization.CultureInfo.GetCultureInfo("fr-FR").NumberFormat; 
Decimal.ToString("c", ni); 

を、すべて私の小数点以下の値(内部的には)常にエンGB小数として扱われ、ひいてはでいます私が必要とするフォーマット。言い換えれば、私のアプリケーションは、現在のスレッド全体に適用される設定を変更できる柔軟性を必要としませんでした。むしろちょうど反対:私は値を異なってフォーマットすることに気をつけました。

+0

あなたはまだ十進数を理解する必要があります(あなたのプログラムで扱う変数は、.NETアプリケーションが使用するカルチャとは何の関係もなく、単なる数値です)。それは、文字列を小数点に変換しようとするとき、または小文字で文字列に変換するとき(つまり、それを印刷するときに)、文化が踏み込んで違いを生み出すときです。 つまり、.Netが出力の文化を扱うためには以前と同じようにすることができますが、外部システムから数値を読み込むときには、文字列としてどの形式であるかを知る必要がありますあなたのシステムに入り、そのように扱います。 – kastermester

+0

また、FR-FRロケールでは小数点と桁区切りのスペースを使用するので、123,00は123,000と評価されます。ロケールは対処するのは難しいことですが、信頼してください、私はあなたの痛みを知っています。 私は複数のロケールでシステムを扱います。私は以下の方法でそれに取り組んでいます。 1.サイトのすべてのユーザー入力は、入力ロケール(fr-FRとしましょう)で受け入れられ、同じロケール(fr-FR)で出力されます。他の場所からの入力を受け入れるときは、InvariantCulture形式で受け入れられます。 – kastermester

+0

こんにちはKastermester、 ご意見ありがとうございました - ご意見をいただきありがとうございます。私は確かに分かりませんが、Decimalタイプは「文化特有」ではないので、私が当初私が持っていた問題に戸惑うことがあったのです。 (私たちの実装では)どんな文化でも入力を受け入れることはできません(そしてその文化を保存し、後でそれを正しくフォーマットすることはできません)ので、本当に必要なのは、特定の.ToString()表現の小数点が常に'en-GB'ですが、ユーザーのロケール内のサイトの他の領域にも10進数値を尊重して表示します。 – Richard

1

多分これは、フォーマットを検出するために任意のより良い方法を知っているが、この

を見てみないことすなわち

 Double.Parse(MyString, ni) 

使い方-rAyt

あなた

 NumberFormatInfo ni = new NumberFormatInfo(); 
     ni.NumberDecimalSeparator = '.'; 

助けることができます

static void Main(string[] args) 
    { 
     // German Format (EUR) 
     CultureInfo ci_de = new CultureInfo("de-DE"); 

     // English Format (GBP) 
     CultureInfo ci_gb = new CultureInfo("en-GB"); 


     string test_de = "1.234.567.890,12"; 
     string test_en = "1,234,567,890.12"; 

     double result_de = 0.0; 
     double result_en = 0.0; 

     try 
     { 
      result_de = Double.Parse(test_en, ci_de.NumberFormat); 
     } 
     catch (FormatException ex) 
     { 
      Console.WriteLine("Number isn't a german format " + ex.InnerException); 
     } 
     try 
     { 
      result_en = Double.Parse(test_en, ci_gb.NumberFormat); 
     } 
     catch (FormatException ex) 
     { 
      Console.WriteLine("Number isn't a english format " + ex.InnerException); 
     } 

     Console.WriteLine(result_de.ToString()); 
     Console.WriteLine(result_en.ToString()); 

     Console.ReadLine(); 
    } 
+0

こんにちは、お返事ありがとうございます。私はni.NumberDecimalDigits = "を試しました。 (vb.net)ただし、形式の例外が生成されます。 ni.CurrencyDecimalSeparator = "。"を意味しますか? – Richard

+0

コード全体を含めてください。それは大いに役立ちます。もちろん、CurrencyDecimalSeparatorも使用できます。しかし、ユーロ(100,00)からGBP "100.00"に変換する場合、CurrencyDecimalSeparator = 'に設定する必要があります。 –

+0

これは、明示的に*知っていればうまくいきます。* EURからGBPに変換しています。それはいつものケースではありません。では、どのような設定を使用するのか(純粋に10進数の値から)をどのように検出できますか?ありがとう – Richard

1

10進数のデータ型は、基本的に数値を保持しています。暗黙的に適用される書式はありません。数値が異なる形式で表示されているため、数値の値は変更されません。

おそらく、Webページから入力を文字列として受け取ったときに、正しく解析していない可能性があります。

+0

こんにちはジム、私はあなたが絶対に正しいと思っています...私はロケールに関係なく、デバッガで、小数点以下の値の値varは常に '123.00' 00 '。私の問題は、文字列に変換するときに、あなたが言うように、行のどこかで発生しているに違いありません。 – Richard

0

rAytは良いスタートを提供しましたが、さまざまな文化を扱っている場合、10進数の文化を自動的に検出することは非常に困難になる可能性があります。常に理解するために、文化を含む小数点の周りに単純なラッパー型を作成することが最善の方法かもしれません。カルチャコード(つまり、en-US)も保存するようにデータストアを更新する必要があります。そのため、データを再構築するときに、データが保存されたカルチャを「忘れない」ようにします。あなたが持っている任意のエンティティは、直接ではなく、小数点よりも、あなたの小数ラッパー型を使用して、そのタイプは、自動的に正しい形式でレンダリングするオーバーライドされたToStringメソッドかもしれない:彼らの経験と提案を提供したすべての人に

public struct CulturedDecimal 
{ 
    public decimal Value; 
    public CultureInfo Culture; 

    public override ToString() 
    { 
     return Value.ToString(Culture); 
    } 
} 

public class SomeEntity 
{ 
    public int ID { get; set; } 
    public CulturedDecimal MonetaryValue { get; set; } // Was 'decimal' before 
} 
関連する問題