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

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

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

No.54359 の関連記事表示

<< 0 >>
■54359  割合計算について
□投稿者/ ヤスト -(2010/10/14(Thu) 20:20:21)

    分類:[Java] 

    2010/10/14(Thu) 20:22:31 編集(投稿者)
    2010/10/14(Thu) 20:22:23 編集(投稿者)

    public static void main(String[] args) {

      //配列
      int data[]={150,25,25,14};
      
      for(int i=0; i<data.length; i++){

       total +=data[i];

      }

      int a = (int)Math.round((double)data[0]/total*100);
    int b = (int)Math.round((double)data[1]/total*100);
    int c = (int)Math.round((double)data[2]/total*100);
    int d = (int)Math.round((double)data[3]/total*100);

      }

    この実行結果は
    int a = 70
    int b = 12
    int c = 12
    int d = 7

    合計:101

    合計を100で出力させたいのですが、端数が出てきてしまいます。
    このような場合は、どう対処すればよいのでしょうか。


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

■54360  Re[1]: 割合計算について
□投稿者/ やじゅ -(2010/10/14(Thu) 20:58:01)
>
    2010/10/14(Thu) 21:02:26 編集(投稿者)

    No54359 (ヤスト さん) に返信
    > この実行結果は
    > int a = 70
    > int b = 12
    > int c = 12
    > int d = 7
    >
    > 合計:101
    >
    > 合計を100で出力させたいのですが、端数が出てきてしまいます。
    > このような場合は、どう対処すればよいのでしょうか。

    基本は切り捨てにして、端数分をどこかに足すようにすればいいんじゃない。
    もしく四捨五入にしたとしても、100からの差をどこかで調整する。
    どこに調整するかは、仕様で決めておく。
    一番少ないところに足すとか、一番多いところに足すとか、最後の値に足すとか
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54361  Re[2]: 割合計算について
□投稿者/ かたぎり -(2010/10/15(Fri) 01:47:34)
    やり方は色々とありますけれど、
    必ず整数でなければならない場合には、やじゅさんの方法が楽でしょうね。
    もっと厳密にDouble値で、というのであれば、
     
      100<=で最も100に近く低い整数にして、100を引いた端数を要素数で割ってそれぞれから引く
    or 100=>で最も100に近く高い整数にして、100から引いた端数を要素数で割ってそれぞれに足す

    限りなく、100に近く、割合も偏らない結果になれるはずですが、必ず100になるとは保証できません。

記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54362  Re[3]: 割合計算について
□投稿者/ なちゃ -(2010/10/15(Fri) 08:34:29)
    No54361 (かたぎり さん) に返信
    > もっと厳密にDouble値で、というのであれば、
    >  
    >   100<=で最も100に近く低い整数にして、100を引いた端数を要素数で割ってそれぞれから引く
    > or 100=>で最も100に近く高い整数にして、100から引いた端数を要素数で割ってそれぞれに足す
    >
    > 限りなく、100に近く、割合も偏らない結果になれるはずですが、必ず100になるとは保証できません。

    これが出来るなら最初から普通に計算するだけなのでは?

    どうしても合わせたいなら、誤差のトータルから適切な要素に振り分けるしかないでしょうけど、
    そもそも合わす必要が無いのでは?という気もします。
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54366  Re[4]: 割合計算について
□投稿者/ 中博俊 -(2010/10/15(Fri) 11:54:56)
    > どうしても合わせたいなら、誤差のトータルから適切な要素に振り分けるしかないでしょうけど、
    > そもそも合わす必要が無いのでは?という気もします。

    お金の配賦なんかじゃ絶対にあわせないといけませんからね
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54368  Re[5]: 割合計算について
□投稿者/ なちゃ -(2010/10/15(Fri) 12:41:57)
    No54366 (中博俊 さん) に返信
    > お金の配賦なんかじゃ絶対にあわせないといけませんからね

    額の振り分けならそうですけど、今の計算は各金額のパーセント値を出したいだけに見えたので。

    まあ会計的なことは分かりませんが、合計100になるように数値を操作するのも
    それはそれでおかしい気がしたりもするんですけどね。
    まあ用途によるでしょうけども。
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54369  Re[6]: 割合計算について
□投稿者/ ミラ -(2010/10/15(Fri) 13:15:50)
    2010/10/15(Fri) 13:17:59 編集(投稿者)

    とりあえず100になればいいのであれば最後の数字だけ調整すればいいんですかね

    public static void main(String[] args) {

    // 配列
    int data[] = { 150, 25, 25, 14 };
    int total = 0;

    for (int i = 0; i < data.length; i++) {
    total += data[i];

    }

    int result[] = new int[data.length];

    int total_process = 0;

    for (int i = 0; i < data.length - 1; i++) {
    result[i] = (int)Math.round((double)data[i]/total*100);
    total_process+=result[i];
    }
    result[data.length - 1] = 100 - total_process;

    }

    次に長いですが端数の小さいものを大きいものに移動する方法で考えてみました
    javaは不勉強なのでコードに無駄が多少ありますがこんなのでどうでしょうか?

    public static void main(String[] args) {

    // 配列
    int data[] = { 150, 25, 25, 14 };
    int total = 0;

    for (int i = 0; i < data.length; i++) {
    total += data[i];

    }

    int result[] = new int[data.length];
    double result_hasu[] = new double[data.length];

    for (int i = 0; i < data.length; i++) {
    result_hasu[i] = (double) data[i] / total * 100;
    result[i] = (int) result_hasu[i];
    result_hasu[i] -= result[i];
    }

    do {
    int maxindex = -1;
    int minindex = -1;
    // 最大端数と最小端数のindexを算出
    for (int i = 0; i < data.length; i++) {
    if (result_hasu[i] == 0 || result_hasu[i] == 1) {
    continue;
    }
    if (maxindex == -1) {
    maxindex = i;
    }
    if (minindex == -1) {
    minindex = i;
    }
    if (result_hasu[maxindex] < result_hasu[i]) {
    maxindex = i;
    }
    if (result_hasu[minindex] > result_hasu[i]) {
    minindex = i;
    }
    }
    if (maxindex != -1) {
    if (minindex != -1 && maxindex != minindex) {
    // 最大端数が1になるまで最小端数を移動
    double add = Math.min(1 - result_hasu[maxindex],
    result_hasu[minindex]);
    result_hasu[maxindex] += add;
    result_hasu[minindex] -= add;
    } else {
    break;
    }
    }
    } while (true);

    for (int i = 0; i < data.length; i++) {
    // 端数を結果に戻す
    result[i] += Math.round(result_hasu[i]);
    }
    }
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54374  Re[6]: 割合計算について
□投稿者/ やじゅ -(2010/10/15(Fri) 18:37:46)
>
    なんか、サラミ法を使った犯罪を思い出しました。
    ■60年代末に発覚したニューヨーク在住の銀行員の犯行:
     顧客の預金利子を計算するプログラムで端数処理を四捨五入ではなく
     すべて切り捨て計算とし、剰余の利息を自分名義の口座に自動振込す
     るプログラムも付け加えて巨額の不正入金を得た。

    設計時の見落とし − 按分処理後の端数補正
    http://blog.yaju.jp/200812/article_12.html
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54377  Re[7]: 割合計算について
□投稿者/ れい -(2010/10/16(Sat) 01:56:15)
    > 合計を100で出力させたいのですが、端数が出てきてしまいます。
    > このような場合は、どう対処すればよいのでしょうか。

    用途とか業界によって違います。
    基本は「悪意」が無いということがわかるようにすることです。

    やじゅさん。
    > どこに調整するかは、仕様で決めておく。
    > 一番少ないところに足すとか、一番多いところに足すとか、最後の値に足すとか

    ほとんどの場合一番少ないところに足すことはないでしょう。
    誤差が大きくなるので。

    会計だとか経理だとかの場合、
    四捨五入ではなく「最近接偶数への丸め&#8206;」を行って、
    「その他」の項目がある場合はそこに含め、
    ない場合は「一番大きいところ」に誤差を集めるのが普通でしょう。
    一番大きいところは四捨五入の誤差がたまっても相対的に誤差が少なくなります。

    数値計算などで、合計よりも個々の項目の絶対値が重要である場合は
    合計を100にするのをあきらめるのが正しくなります。

    項目が均等に分布しておらず、統計処理のためだけに用いる場合などでは
    乱数を用いて丸めを行う場合もあります。
    この場合、最後の項目でうまく帳尻が合うようにできます。

    銀行の口座のように「サラミ」が問題になるような場合は「丸め誤差」という項目を入れることが正しい場合があります。

    いずれにせよ、時と場合次第、です。
    一般的な指針は最初に述べたように「悪意が入りこんでいない」ことがわかるようにすることです。

    #最近接偶数丸めは「JIS Z 8401」を参照。
    #会計・経理等に関しては規格かなにか決まっていと思うのですが、
    #机をごそごそしても資料は見つかりませんでした。
記事No.54359 のレス /過去ログ91より / 関連記事表示
削除チェック/

■54427  Re[8]: 割合計算について
□投稿者/ ヤスト -(2010/10/19(Tue) 21:47:33)

    ミラさん

    ミラさんのコードで、割合計算が正常に行えるようになりました。
    ありがとうございました。
記事No.54359 のレス / END /過去ログ91より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -