68741


以下のコードをAndroid Studioで一応実行することはできるのですが、`calorie` に対して BigDecimal で setScale
をしているにもかかわらず、四捨五入されずに小数点以下5桁くらいまで表示されてしまっています。

`calorie` を求めるにあたって `weight`, `height`, `age` は BigDecimal での計算はしていません。最終的に求まる
`calorie` に対して BigDecimal で setScale をしたら四捨五入されるという認識でいました。

[code]

    import android.os.Bundle;
    import android.widget.EditText;
    import android.widget.Spinner;
    import android.widget.TextView;
    import androidx.appcompat.app.AppCompatActivity;
    import java.math.*;
    
    
    public class MainActivity extends AppCompatActivity {
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
        }
    
        //　決定ボタン
        public void onClickButton(android.view.View view) {
            TextView calorieForm = this.findViewById(R.id.calorieForm);
            TextView proteinForm = this.findViewById(R.id.proteinForm);
            TextView carbonForm = this.findViewById(R.id.carbonForm);
            TextView fatForm = this.findViewById(R.id.fatForm);
            EditText ageForm = this.findViewById(R.id.ageForm);
            EditText weightForm = this.findViewById(R.id.weightForm);
            EditText heightForm = this.findViewById(R.id.heightForm);
    
            // Spinnerオブジェクトを取得
            Spinner spinner = findViewById(R.id.spinnerSex);
            Spinner spinner1 = findViewById(R.id.活動レベルForm);
    
            // 選択されているアイテムを取得
            String item = (String)spinner.getSelectedItem();
            String item1 = (String)spinner1.getSelectedItem();
    
    
            String strAge;
            strAge = ageForm.getText().toString();
            String strWeight;
            strWeight = weightForm.getText().toString();
            String strHeight;
            strHeight = heightForm.getText().toString();
    
            double protein, carbon, fat, age, weight, height;
            age = Double.parseDouble(strAge);
            weight = Double.parseDouble(strWeight);
            height = Double.parseDouble(strHeight);
    
            // case文で処理したい
            double calorie = 0;
            BigDecimal bd = BigDecimal.valueOf(calorie);
            bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);      /* 左辺のbdが黒文字化？反映されていない　*/
    
    
            if (item.equals("男性") && item1.equals("ほぼ運動しない")) {
                calorie = (13.397 * weight + 4.799 * height - 5.677 * age + 88.362) * 1.2;
            } else if (item.equals("男性") && item1.equals("軽い運動をしている")) {
                calorie = (13.397 * weight + 4.799 * height - 5.677 * age + 88.362) * 1.375;
            } else if (item.equals("男性") && item1.equals("中程度の運動をしている")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.55;
            } else if (item.equals("男性") && item1.equals("激しい運動をしている")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.725;
            }  else if (item.equals("男性") && item1.equals("非常に激しい運動をしている")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.9;
            }  else if (item.equals("女性") && item1.equals("ほぼ運動しない")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.2;
            }  else if (item.equals("女性") && item1.equals("軽い運動をしている")) {
                calorie = (13.397 * weight + 4.799 * height - 5.677 * age + 88.362) * 1.375;
            } else if (item.equals("女性") && item1.equals("中程度の運動をしている")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.55;
            } else if (item.equals("女性") && item1.equals("激しい運動をしている")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.725;
            }  else if (item.equals("女性") && item1.equals("非常に激しい運動をしている")) {
                calorie = (9.247 * weight + 3.098 * height - 4.33 * age + 447.593) * 1.9;
            }
            protein = weight * 2.3;
            carbon = weight * 2.65;
            fat = weight * 0.9;
    
    
            String msg0 = calorie + "cal";
            String msg1 = protein + "g";
            String msg2 = carbon + "g";
            String msg3 = fat + "g";
    
            calorieForm.setText(msg0);
            proteinForm.setText(msg1);
            carbonForm.setText(msg2);
            fatForm.setText(msg3);
        }
    
    
[/code]


CC BY-SA 4.0
2020-07-19T16:24:24.633
68738
2021-03-07T04:24:05.540
2021-03-07T04:24:05.540
3060
40944
question
java android
BigDecimalを用いても四捨五入されません。


こんにちは、はじめまして。

BigDecimalは大きな数値を精度をコントロールして利用するためのクラスになり、通常の数値型に代替するものではありません。

<https://docs.oracle.com/javase/jp/8/docs/api/java/math/BigDecimal.html>  
<https://techacademy.jp/magazine/18597>

浮動小数点の精度により丸め誤差が生じるため存在します。僕の分野ではあまり使うことはないですが、精度を予測内に収めたい場合などには便利そうですね。

上のtechacademyからの引用ですが下記のように扱います。

[code]

    BigDecimal b1 = new BigDecimal("3.1415");
    BigDecimal b2 = new BigDecimal("9.9");
    BigDecimal b3 = b1.multiply(b2);
    
[/code]

すべての値をBigDecimalにして上記のようにメソッドで演算すれば目的の結果が得られるはずです。

ですがコードの目的は小数点1桁で四捨五入をして結果を表示したいという点ではないでしょうか?  
weight,heightなどがdoubleと仮定して下記の式を小数点1桁で丸めるとすると下記の二つの例が考えられます。

calorie1. 10倍したものを四捨五入して、割りなおす。四捨五入にはMath.round命令を用います。  
calorie2. 出力時に文字列にするのでその時点でString.formatする(仕様上、自動的に四捨五入されます)。

[code]

    import java.lang.Math;
    
    public class MyClass {
        public static void main(String args[]) {
          double weight = 65.23;
          double height = 171.15;
          double age = 28.45234;
    
          double calorie1 = (Math.round(((13.397 * weight + 4.799 * height - 5.677 * age + 88.362) * 1.2)*10))/10.0;
          System.out.println("calorie=" + calorie1);
          double calorie2 = (13.397 * weight + 4.799 * height - 5.677 * age + 88.362) * 1.2;
          System.out.println("calorie=" + String.format("%.1f",calorie2));
        }
    }
    
[/code]

参考 URL :  
<https://blog.apar.jp/program/8900/>  
<http://hensa40.cutegirl.jp/archives/5620>


CC BY-SA 4.0
2020-07-20T02:26:59.373
68741
2020-07-20T02:38:46.080
2020-07-20T02:38:46.080
37777
37777
68738
answer


回答していただきありがとうございます。

`Math.round` を使ってみた結果、少数1桁で表示させることができました。  
`System.out.println` が上手く噛み合わなかったので、その部分は使いませんでした。原因として、最後のほうに

[code]

    String msg0 = calorie + "cal";　
    calorieForm.setText(msg0);
    
[/code]

を用いてtexitviewに反映されるようにしてあるかなと考えています。全然違っていたらすみません。

[code]

    double calorie = 0;
    if (item.equals("男性") && item1.equals("ほぼ運動しない")) {
        calorie = (Math.round((13.397 * weight + 4.799 * height - 5.677 * age + 88.362) * 1.2)*10)/10.0;
    } 
    
    String msg0 = calorie + "cal"; 
    calorieForm.setText(msg0);
    
[/code]


CC BY-SA 4.0
2020-07-20T04:18:14.700
68742
2020-07-20T12:37:55.603
2020-07-20T12:37:55.603
32986
40944
68738
answer


> `calorie` に対して BigDecimal で setScale
> をしているにもかかわらず、四捨五入されずに小数点以下5桁くらいまで表示されてしまっています。

質問されている事項の原因は、出力対象にしている `calorie` は `double` 型であり、 `BigDecimal` 型として宣言している
`bd` は計算過程に一切関与していないためです。

[code]

    // 表示対象として利用しているのは bd(BigDecimal) でなく calorie(double)
    String msg0 = calorie + "cal";
    
[/code]

代わりに、ここで `calorie` の値を `BigDecimal` に変換して利用します。

[code]

    BigDecimal bd = new BigDecimal(calorie);
    bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);
    // 表示対象は calorie の値を BigDecimal型に変換したもの
    String msg0 = bd.toString() + "cal";
    
[/code]

* * *

ちなみに今回のように出力を整形したいだけの場合は、(`BigDecimal` に変換するのではなく) `double`型変数の値に対して
[`String.format()`](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html#format-
java.lang.String-java.lang.Object...-)
で[書式文字列`f`](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Formatter.html#dndec)を適用するのが自然かなと思います。

[code]

    String msg0 = String.format("%.1fcal", calorie);
    
[/code]


CC BY-SA 4.0
2020-07-20T17:27:54.890
68764
2020-07-20T22:19:59.570
2020-07-20T22:19:59.570
2808
2808
68738
answer