質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

解決済

KMGT変換で「999999」にすると1Mになってしまう

MissingPiece598
MissingPiece598

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

3回答

0グッド

0クリップ

327閲覧

投稿2022/11/25 11:24

前提

数値をKMGTに変換する処理を作成しました。
ただ「999999」を変換すると1Mになってしまいます。

おそらく下記の部分が不具合の原因かと思いますが、修正方法がわかりません。

C#

1 //有効桁数3桁+指数表記で文字列化 2    //※ここが原因?  3 var s = d.ToString("0.00E000");

ご教授いただければ幸いです。

実現したいこと

「999999」を変換すると"999.9K"になるのが理想です。

該当のソースコード

C#

1 /// <summary> 2 /// 単位をつけた文字列に変換します。 3 /// 12 -> 12 4 /// 1234 -> 1.23k 5 /// 123456 -> 123k 6 /// 12345678 -> 12.3m 7 /// 8 /// 単位:k, m, b, t, A, B, C, ... Z, AA, AB, AC, ... 9 /// 10 /// </summary> 11 /// <param name="d"></param> 12 /// <returns></returns> 13 public static string ToReadableString(this double d) 14 { 15 //マイナスは扱う気無し 16 if (d <= 0) return "0"; 17 //表示上は整数として見せるので、suffix(kmbtABC等)がつかない場合は少数部を破棄 18 if (d <= 1000) return ((int) d).ToString(); 19 20 //有効桁数3桁+指数表記で文字列化 21    //※ここが原因?  22 var s = d.ToString("0.00E000"); 23 24 //有効数字 25 float f = float.Parse(s.Substring(0, 4)); 26 27 //10の指数 28 var e = int.Parse(s.Substring(5, 3)); 29 30 //中途半端な指数は数値に掛け合わせておく 31 for (var i = 0; i < e % 3; i++) 32 { 33 f *= 10; 34 } 35 36 return f.ToString("###.##") + LevelToSuffix(e / 3); 37 } 38 39 /// <summary> 40 /// 10^3ごとにつけるSuffixの一覧 41 /// </summary> 42 private static string[] _suffixes; 43 44 private static string LevelToSuffix(int level) 45 { 46 if (_suffixes == null) 47 { 48 const string AtoZ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 49 var list = new List<string>(); 50 list.Add(""); 51 list.Add("k"); 52 list.Add("m"); 53 list.Add("b"); 54 list.Add("t"); 55 for (var x = 0; x < AtoZ.Length; x++) 56 for (var y = 1; y < AtoZ.Length; y++) 57 { 58 var str = string.Format("{0}{1}", AtoZ[x], AtoZ[y]).Trim(); 59 list.Add(str); 60 } 61 62 _suffixes = list.Take(308).ToArray(); //doubleは指数308まで 63 } 64 65 return _suffixes[level]; 66 }

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答3

0

何らかの課題でしょうか。だとすれば設問に問題がありますね。
というのも、コードを見るに非常に大きい数まで扱いたいようですが、引数がdoubleである限り正確な値が扱えるのはわずか2^53≒9007兆までです。(この記法でいうなら9.007A)
正確でない値をどうするかで考えられるスタンスがいくつかあるので、どういう回答を求められているのか(どうせ上の方は正確でないのに999999が1Mになるのも許容しないのか)、引数がdoubleなのは変えられないのかあたりが分からないとどうにも答えようがありません。

まあ、(引数を文字列にしたいところだが無理なら)適当にやるならdouble最大の17桁で文字列化してから文字列処理をすれば、文字列化が正しく行われる前提で、doubleとして最大限正しい値は出ると思います。
文字列化に正しさを丸投げしているわけですが、(大昔は誤った出力が出ることもあったようだが)最近のまともな環境ならたぶん大丈夫でしょう。

投稿2022/11/26 10:26

ikadzuchi

総合スコア3004

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

指数表記にこだわらなければ、いかようにでも作れると思いますが・・・

CSharp

1using System; 2using System.Collections.Generic; 3using System.Linq; 4 5internal static class Program 6{ 7 static void Main(string[] args) { 8 print(999999d); 9 print(1000000d); 10 print(12d); 11 print(1234d); 12 print(123456d); 13 print(12345678d); 14 Console.ReadKey(); 15 } 16 17 static void print(double d) { 18 Console.WriteLine($"{d} => {d.ToReadableString()}"); 19 } 20 21 public static string ToReadableString(this double d) { 22 var sign = Math.Sign(d); 23 var value = Math.Abs(d); 24 int i; 25 for (i = 0; i < suffixes.Length - 1; i++) { 26 if (value < 1000) { 27 break; 28 } 29 value = Math.Truncate(value / 10) / 100; 30 } 31 var str = (value * 1000).ToString(); 32 if (str.Length > 3) { 33 str = str.Substring(0, 3) + new string('0', str.Length - 3); 34 } 35 value = double.Parse(str) / 1000; 36 return (sign * value).ToString() + suffixes[i]; 37 } 38 39 private static string[] _suffixes; 40 private static string[] suffixes { 41 get { 42 if (_suffixes == null) { 43 const string AtoZ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 44 var list = new List<string>(); 45 list.Add(""); 46 list.Add("k"); 47 list.Add("m"); 48 list.Add("b"); 49 list.Add("t"); 50 for (var x = 0; x < AtoZ.Length; x++) 51 for (var y = 1; y < AtoZ.Length; y++) { 52 var str = string.Format("{0}{1}", AtoZ[x], AtoZ[y]).Trim(); 53 list.Add(str); 54 } 55 _suffixes = list.Take(308).ToArray(); 56 } 57 return _suffixes; 58 } 59 } 60}

ところで、頭3桁のみ有効桁にするのであれば、999999 → 999k になるのでは?

投稿2022/11/26 04:16

編集2022/11/26 10:27
KOZ6.0

総合スコア2243

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

ベストアンサー

「999999」を変換すると"999.9K"になるのが理想です。

 一般的な丸め処理では、そうはなりません。

 通常、有効桁数を減らす場合、四捨五入など、誤差が小さくなるように変換します。
なので、999999 を "0.00E000" で文字列にする場合、まず、丸め処理で、1000000になるので、ご希望の結果にはなりません。
質問者さんの仕様を満たすためには、文字列にする前に、切り捨てによる丸め処理を行うことが必要です。

投稿2022/11/25 15:58

YT0014

総合スコア1591

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

MissingPiece598

2022/11/25 16:57

下記のようにした見たのですが、うまくいきません。 「文字列にする前に、切り捨てによる丸め処理」とはどのようにしたらよいでしょうか。 お手数ですが、ご教授いただけないでしょうか。 //dが「999999」     string temp = d.ToString(); //有効桁数3桁 int significantDigit = int.Parse(temp.Substring(0, 3)); //指数表記で文字列化 var suffix = significantDigit.ToString("0.00E000");
YT0014

2022/11/26 08:17

順番が逆です。 文字列返還の前に切り捨てです。 桁数不明なので、割と面倒な処理をしないと切り捨てできません。 未チェックですが、以下にコード // 上から3桁目の桁数の取得 int digit = (int)Math.Log10(d) - 2; // 上から3桁目を示す10の乗数を計算 double base = Math.Pow(10.0, (double)digit); // 切り捨てで上位3桁のみにする double d2 = Math.Floor(d / base) * base;
MissingPiece598

2022/11/26 11:38

ご回答ありがとうございます。 999kになりました、変換すると"999.9K"にする方法自力で見つけたいと思います。 ご教示いただきありがとうございます。
YT0014

2022/11/27 03:48

探す前に、こちらで提示したコードを、詳細に理解されることをお勧めします。 (int)Math.Log10(d) は、何を求めているのか? なぜ、2を引いているのか? Math.Pow(10.0, (double)digit) は、何を求めているのか? Math.Floor(d / base) * base は、何を求めているのか? 以上の質問に答えられますか? 参考までに、各関数のヘルプを挙げておきます。 https://learn.microsoft.com/ja-jp/dotnet/api/system.math.log10?view=net-7.0 https://learn.microsoft.com/ja-jp/dotnet/api/system.math.pow?view=net-7.0 https://learn.microsoft.com/ja-jp/dotnet/api/system.math.floor?view=net-7.0

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。