C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

全過去ログを検索

<< 0 >>
■53954  Re[1]: Bitmapデータをjpeg圧縮
□投稿者/ shu -(2010/09/30(Thu) 16:43:06)
    No53953 (α さん) に返信
    Bitmap.SaveはStreamに対応しているので
    BinaryStreamを使ってByte配列にするというのはどうでしょう?
記事No.53953 のレス /過去ログ90より / 関連記事表示
削除チェック/

■78580  Re[1]: FTP ファイルダウンロード エラー処理
□投稿者/ とっちゃん -(2016/01/27(Wed) 10:32:09)
    No78577 (ぎみっく さん) に返信
    > 下記のようにファイルをダウンロードしているのですが
    > サーバーに繋がらない時やファイルが存在しなかった時の記述方法がわかりません
    >
    >
    > Dim wc As New WebClient()
    > wc.Credentials = New System.Net.NetworkCredential(ftpid, ftppass)
    > wc.DownloadFile(ftpadd & hostdir & sorcefile1, sorcedir1)
    >
    > これにどう追記したら良いのでしょうか?
    > サーバーに繋がらない時やファイルが存在しなかった時には、c:\ の同一ファイル
    > 無ければエラーメッセージを出したいのですが
    > サーバー管理のエラー処理のきじゅつがわかりません
    >
    WebClient.DownloadFile のリファレンスにも出ていますが、
    エラーが発生した場合、それなりの理由を持った例外が発生します。

    なので、例外処理を行えばよいと思います。
記事No.78577 のレス /過去ログ133より / 関連記事表示
削除チェック/

■85832  指数表記された文字列の数値変換方法について
□投稿者/ たかじ -(2017/11/28(Tue) 17:28:42)

    分類:[.NET 全般] 

    お世話になっております。

    指数表記されている文字列(2.12345678975E9や3.4E+38など)を
    decimalにTryParseすると、変換に失敗します。

    指数表記ありの文字列を、.NET標準の機能でdecimalに変換することは可能でしょうか?
    ご存じの方いっしゃいましたら、変換方法を教えて頂けないでしょうか。

    環境:
    Visual Studio 2013 Professional
    .NET 4.0

    以上、よろしくお願いいたします。
親記事 /過去ログ147より / 関連記事表示
削除チェック/

■85833  Re[1]: 指数表記された文字列の数値変換方法について
□投稿者/ WebSurfer -(2017/11/28(Tue) 18:07:12)
    No85832 (たかじ さん) に返信

    > 指数表記ありの文字列を、.NET標準の機能でdecimalに変換することは可能でしょうか?

    Decimal.TryParse メソッド (String, NumberStyles, IFormatProvider, Decimal) という
    オーバーロードがありますが、それは使えませんか?
記事No.85832 のレス /過去ログ147より / 関連記事表示
削除チェック/

■85853  Re[1]: 指数表記された文字列の数値変換方法について
□投稿者/ 魔界の仮面弁士 -(2017/11/29(Wed) 09:42:45)
    No85832 (たかじ さん) に返信
    > 指数表記されている文字列(2.12345678975E9や3.4E+38など)を
    > decimalにTryParseすると、

    Decimal ではなく decimal と表記されていることからして、
    VB ではなく C# をお使いでしょうか。


    > 変換に失敗します。

    前者は、NumberStyles を受け取る TryParse のオーバーロードを使えば変換できますが、
    後者はどうやっても不可能です。最大値(decimal.MaxValue)を大幅に超えていますから…。

    3.4E+38 はおろか、3.4E+29 でも不可能です。(3.4E+28 なら変換できますけれども)
    System.Decimal の scale は 0〜28 の範囲しか指定できません。
    https://msdn.microsoft.com/ja-jp/library/bb1c1a6x.aspx


    なお System.Decimal は、有効桁数も含めて保持されるため、
     string s1 = "2.12345678975E9";

     string s2 = "2.12345678975000E9";
    は異なる変換結果になることにご注意ください。

    string s1 = "2.12345678975E9";
    string s2 = "2.12345678975000E9";

    NumberStyles ns = NumberStyles.AllowExponent | NumberStyles.Float;
    IFormatProvider fmt = CultureInfo.InvariantCulture;

    decimal d1, d2;
    Console.WriteLine(decimal.TryParse(s1, ns, fmt, out d1));
    Console.WriteLine(decimal.TryParse(s2, ns, fmt, out d2));
    Console.WriteLine(d1 == d2); // 値としては同じ
    Console.WriteLine(d1); // 有効桁数12桁で表示される
    Console.WriteLine(d2); // 有効桁数15桁で表示される
記事No.85832 のレス /過去ログ147より / 関連記事表示
削除チェック/

■85904  Re[2]: 指数表記された文字列の数値変換方法について
□投稿者/ たかじ -(2017/11/30(Thu) 16:33:49)
    WebSurferさん、魔界の仮面弁士さん

    ご連絡が遅くなりすみません。
    ご回答ありがとうございます。

    遅くなりましたが、開発言語はC#です。

    ご丁寧にサンプルも記載して頂き、わかりやすかったです。
    指数表記の数値変換方法については、
    ご掲示頂いた内容で解決することができました。
    ありがとうございます。

    ※魔界の仮面弁士さんにご掲示頂くまで、
    decimal有効桁数の存在をすっかり忘れていました。。。

    3.4E+38の変換については、型の問題もありますので、解決方法検討してみます。
記事No.85832 のレス / END /過去ログ147より / 関連記事表示
削除チェック/

■85915  Re[3]: 指数表記された文字列の数値変換方法について
□投稿者/ 魔界の仮面弁士 -(2017/12/01(Fri) 11:13:23)
    # 解決済みマークはつけたままにしておきます。

    No85904 (たかじ さん) に返信
    >>> 指数表記されている文字列(2.12345678975E9や3.4E+38など)を
    >>> decimalにTryParseすると、変換に失敗します。
    >> 後者はどうやっても不可能です。最大値(decimal.MaxValue)を大幅に超えていますから…。
    > 3.4E+38の変換については、型の問題もありますので、解決方法検討してみます。


    値が大きいので、基本的には System.Single や System.Double の
    出番な気がしますが、最終的には要件が求める許容誤差次第ですね。


    あとは System.Numerics.BigInteger を使う手もありますが、
    あくまで整数なので、"3.4E+38" はパースできても、
    "2.12345678975E9" の方には使えません。


    using System;
    using System.Globalization;
    using System.Numerics; // 参照設定: System.Numerics.dll
    class Program
    {
     static void Main()
     {
      var ns = NumberStyles.Float;
      var fmt = CultureInfo.InvariantCulture;

      string s1 = "2.12345678975E9";
      decimal dm; double d1; float f1;
      decimal.TryParse(s1, ns, fmt, out dm); // true
      double.TryParse(s1, ns, fmt, out d1);  // true
      float.TryParse(s1, ns, fmt, out f1);  // true
      Console.WriteLine("{0:N4}", dm); // 2,123,456,789.7500
      Console.WriteLine("{0:N4}", d1); // 2,123,456,789.7500
      Console.WriteLine("{0:N4}", f1); // 2,123,457,000.0000

      string s2 = "3.4E+38";
      BigInteger b1, b2, b3; double d2; float f2;
      BigInteger.TryParse(s2, ns, fmt, out b1); // true
      double.TryParse(s2, ns, fmt, out d2);   // true
      float.TryParse(s2, ns, fmt, out f2);    // true
      b2 = (BigInteger)d2;
      b3 = (BigInteger)f2;
      Console.WriteLine("{0:N4}", b1); // 340,000,000,000,000,000,000,000,000,000,000,000,000.0000
      Console.WriteLine("{0:N4}", d2); // 340,000,000,000,000,000,000,000,000,000,000,000,000.0000
      Console.WriteLine("{0:N4}", b2); // 339,999,999,999,999,996,123,846,586,046,231,871,488.0000
      Console.WriteLine("{0:N4}", b3); // 339,999,995,214,436,424,907,732,413,799,364,296,704.0000

      Console.ReadKey();
     }
    }


    あとは、nuget などからの導入になりますが、BigDecimal とかですかね。


    Deveel.Math.BigDecimal v1, v2, v3;
    Deveel.Math.BigDecimal.TryParse("2.12345678975E9", out v1);
    Deveel.Math.BigDecimal.TryParse("3.4E+38", out v2);
    Deveel.Math.BigDecimal.TryParse("340000000000000000000000000000000000000", out v3);

    上記はいずれも true を返しますが、値の大小比較をする際には注意が必要です。
    v2 と v3 は、数値的には同じ値ですが、有効桁数が異なりますので。

    Console.WriteLine(v2.CompareTo(v3)); // 0 (一致)
    Console.WriteLine(v2 == v3);  // False (不一致)
    Console.WriteLine("{0}", v1); // 2123456789.75
    Console.WriteLine("{0}", v2); // 3.4E+38
    Console.WriteLine("{0}", v3); // 340000000000000000000000000000000000000

    ※ v2 は 指数 -37、有効桁数 2 桁 ( 34 × 10 ^ -37)
    ※ v3 は 指数 0、有効桁数 39 桁 (340000000000000000000000000000000000000 × 10 ^ 0)
記事No.85832 のレス / END /過去ログ147より / 関連記事表示
削除チェック/

■85967  Re[4]: 指数表記された文字列の数値変換方法について
□投稿者/ たかじ -(2017/12/06(Wed) 10:14:15)
    No85915 (魔界の仮面弁士 さん) に返信

    解決方法のご提案までありがとうございます。

    Deveel.Math.BigDecimalを初めて知ったので、
    サンプルを作成しながら利用可能か試しているのですが、気になる点があります。
    もしご存知でしたら教えていただけないでしょうか。

    ・BigDecimalの演算はAdd、Subtract、Multiply、Divideのメソッドを使用しないとだめなのでしょうか?
     下記の結果だと、Subtractを使用すると指数表記無しで、*だと指数表記なのも気になります。
    ・指数表記の値をToXXで変換するとエラーが発生するのですが、回避策などありますでしょか?

    Deveel.Math.BigDecimal b1 = 300;
    Deveel.Math.BigDecimal b2 = 10000000;
    Deveel.Math.BigDecimal b3 = b1 * b2;
    Deveel.Math.BigDecimal b4 = b1.Multiply(b2);
    Console.WriteLine("{0}", b1); // 300
    Console.WriteLine("{0}", b2); // 10000000
    Console.WriteLine("{0}", b3); // 3.00E+9
    Console.WriteLine("{0}", (UInt32)b3); // 3000000000
    Console.WriteLine("{0}", b4.ToDecimal()); // 3000000000
    Console.WriteLine("{0}", (decimal)b3); // 3000000000
    Console.WriteLine("{0}", b3.ToDecimal()); // 例外が発生(Negative exponent)

    以上、よろしくお願いいたします。
記事No.85832 のレス /過去ログ147より / 関連記事表示
削除チェック/

■85971  Re[5]: 指数表記された文字列の数値変換方法について
□投稿者/ 魔界の仮面弁士 -(2017/12/06(Wed) 13:31:14)
    2017/12/06(Wed) 14:06:25 編集(投稿者)

    No85967 (たかじ さん) に返信
    > Deveel.Math.BigDecimalを初めて知ったので、
    BigDecimal の実装例は他にもあります(例: No75940 )が、
    その中でも、Deveel は有名どころかと思います。

    Microsoft 製ライブラリによる BigDecimal 実装が欲しければ、
     C:\Windows\assembly\GAC_32\vjslib\2.0.0.0__b03f5f7f11d50a3a\vjslib.dll
    という手もありますが、今回の要件には合わないですね。
    https://blogs.msdn.microsoft.com/dd_jpn/2007/06/26/visual


    > ・BigDecimalの演算はAdd、Subtract、Multiply、Divideのメソッドを使用しないとだめなのでしょうか?

    「x * y」と「y * x」では結果が変わりますよね?

    x * y の右値(y)が何であれ、左値(x)の『精度』が優先されるためです。
    これは乗算だけでなく、加算・減算・除算においても同じことです。

    そして、このクラスにとっての x * y というのは、
    x.Multiply(y, new MathContext(x.Precision)) の意味です。



    //using Deveel.Math:

    BigDecimal b1 = 300;         // 300×10^0
    BigDecimal b2 = 10000000 ;     // 10000000×10^0
    BigDecimal b3 = b1 * b2;      // 300×10^-7
    BigDecimal b4 = b2 * b1;      // 30000000×10^-2
    BigDecimal b5 = b1.Multiply(b2);  // 3000000000
    BigDecimal b6 = b1.Multiply(b2, new MathContext(b1.Precision));
    BigDecimal b7 = b1.Multiply(b2, MathContext.Unlimited);

    Console.WriteLine("{0}", b1); // 300
    Console.WriteLine("{0}", b2); // 10000000
    Console.WriteLine("{0}", b3); // 3.00E+9
    Console.WriteLine("{0}", b4); // 3.0000000E+9
    Console.WriteLine("{0}", b5); // 3000000000
    Console.WriteLine("{0}", b6); // 3.00E+9
    Console.WriteLine("{0}", b7); // 3000000000


    >  下記の結果だと、Subtractを使用すると指数表記無しで、*だと指数表記なのも気になります。

    指数表現を望まないのであれば、ToPlainString メソッドを使ってみてください。


    > ・指数表記の値をToXXで変換するとエラーが発生するのですが、回避策などありますでしょか?
    > Console.WriteLine("{0}", (decimal)b3); // 3000000000
    > Console.WriteLine("{0}", b3.ToDecimal()); // 例外が発生(Negative exponent)

    これについては、キャストで事足りるかとは思ったのですが、
    どうやら駄目そうですね。

    まぁ、もともとは『3.4E+38』を変換するのが目的だったので、
    そもそも decimal 化で良いのか、という懸念もありますが。


    で、実装を見る限りは Hongliang さんが書かれているように、
    単なる実装バグのようです。

    原因については、端折って書くと No85853 で述べた
    精度(あるいは有効桁数)の問題です。

    今回の場合、b3.UnscaledValue は 300 なので、
    仮数部だけ見れば、十分に decimal の範囲なのですが、
    b3.Scale が -3 なので、decimal の指数部に収まらなかったという。


    単に「3000000000」という数値を表すにしても、
     decimal x1 = new Decimal(300000, 0, 0, false, 0); // x1 = 300000M;
     decimal x2 = new Decimal(3000000, 0, 0, false, 1); // x2 = 300000.0M;
     decimal x3 = new Decimal(30000000, 0, 0, false, 2);// x2 = 300000.00M;
    とは書けても、
     decimal x4 = new Decimal(300, 0, 0, false, (byte)-3);
    とするわけにはいかないということで。

    # 実際には、「BigInteger.ValueOf(10L).Pow(-3)」によるエラー
記事No.85832 のレス /過去ログ147より / 関連記事表示
削除チェック/

■85970  Re[5]: 指数表記された文字列の数値変換方法について
□投稿者/ Hongliang -(2017/12/06(Wed) 11:59:52)
    > ・BigDecimalの演算はAdd、Subtract、Multiply、Divideのメソッドを使用しないとだめなのでしょうか?
    >  下記の結果だと、Subtractを使用すると指数表記無しで、*だと指数表記なのも気になります。

    前提として、Decimalと同様に、BigDecimalも有効桁数の概念を持っています。
    つまり、100と1.0E+2と1.000E+2はそれぞれ異なる内部表現を持っています。

    さて、BigDecimal.Multiply(BigDecimal)は、それぞれの仮数部を乗じ、それに指数部の和をくっつけて演算終了です。
    今回の場合、b1, b2はいずれも指数部が0(1)なので、b1.Multiply(b2)も指数部は0のままです。
    計算結果の有効桁数(=仮数部の桁数)は10桁になりますね。

    一方 * 演算子の場合、内部でBigDecimal.Multiply(BigDecimal, MathContext)を呼び出します。
    MathContextは有効桁数などの情報を保持するオブジェクトで、a * bの場合、aの有効桁数が使用されます。
    BigDecimal.Multiply(BigDecimal, MathContext)は、まずBigDecimal.Multiply(BigDecimal)を行った後、MathContextで指定された有効桁数に丸める処理を行います。
    今回の場合、b1が有効数字3桁なので、演算結果は有効数字3桁に丸められてしまいました。

    > ・指数表記の値をToXXで変換するとエラーが発生するのですが、回避策などありますでしょか?

    BigDecimalは、実はDecimalへの型変換は明示暗黙問わずサポートしていないようです。
    (Int16, Int32, Int64, Single, Double, BigInteger, Stringへの暗黙の型変換が定義されている)
    (Decimal)b3 という変換は、実はInt64への暗黙の型変換が間に挟まります。

    で、ToDecimalは、指数部が1以上持つ値に対するケアができていない、ただの実装バグに見えますね。
    回避策は…UnscaledValue, Scaleとかで自前計算するとか。
記事No.85832 のレス /過去ログ147より / 関連記事表示
削除チェック/

■85972  Re[6]: 指数表記された文字列の数値変換方法について
□投稿者/ 魔界の仮面弁士 -(2017/12/06(Wed) 14:16:57)
    2017/12/06(Wed) 15:09:54 編集(投稿者)
    2017/12/06(Wed) 14:45:33 編集(投稿者)

    No85970 (Hongliang さん) に返信
    > で、ToDecimalは、指数部が1以上持つ値に対するケアができていない、ただの実装バグに見えますね。
    バグっぽいですね。

    > 回避策は…UnscaledValue, Scaleとかで自前計算するとか。
    ひとまず、これでどうでしょう。

    internal static class BigDecimalExtensions
    {
     public static decimal ToDecimalValue(this BigDecimal d)
     {
      return d.Add(BigDecimal.Zero, MathContext.Unlimited).ToDecimal();
     }
    }

    ---
    上記を追試してみましたが、Unlimited で補正できるものじゃないですね。
    もっと根本的に、ToDecimal の実装そのものを見直さないと駄目っぽい。

    string s = decimal.MaxValue.ToString(); // "79228162514264337593543950335"

    BigDecimal b = BigDecimal.Parse(s);
    decimal d = b.ToDecimal(); // Decimal.MinusOne を返す!


    ---
    手抜き実装ですが、これだとどうでしょう。

    internal static class BigDecimalExtensions
    {
     public static decimal ToDecimalValue(this BigDecimal d)
     {
      return Decimal.Parse(d.ToPlainString());
     }
    }
記事No.85832 のレス /過去ログ147より / 関連記事表示
削除チェック/

■85999  Re[7]: 指数表記された文字列の数値変換方法について
□投稿者/ たかじ -(2017/12/07(Thu) 19:00:21)
    Hongliangさん、魔界の仮面弁士さん

    お世話になっています。
    ご回答ありがとうございます。

    *とMultiplyの違いについて理解できました。

    ToXXで変換するとエラーが発生すると書きましたが、
    他の変換メソッドでは例外発生しませんでした。確認不足でした。
    ToDecimal変換の不具合とDecimalキャストの問題点と回避案ありがとうございます。

    疑問点については、お二方のご回答で解決できました。
    もう少しDeveel.Math.BigDecimalを使って、
    問題がないか確認してみます。
    また何かあればご相談させてください。

    以上、よろしくお願いします。
記事No.85832 のレス / END /過去ログ147より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -