スタック・オーバーフロー Asked by yuki yuki on September 1, 2021
以下のコードをAndroid Studioで一応実行することはできるのですが、calorie
に対して BigDecimal で setScale をしているにもかかわらず、四捨五入されずに小数点以下5桁くらいまで表示されてしまっています。
calorie
を求めるにあたって weight
, height
, age
は BigDecimal での計算はしていません。最終的に求まる calorie
に対して BigDecimal で setScale をしたら四捨五入されるという認識でいました。
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);
}
こんにちは、はじめまして。
BigDecimalは大きな数値を精度をコントロールして利用するためのクラスになり、通常の数値型に代替するものではありません。
https://docs.oracle.com/javase/jp/8/docs/api/java/math/BigDecimal.html
https://techacademy.jp/magazine/18597
浮動小数点の精度により丸め誤差が生じるため存在します。僕の分野ではあまり使うことはないですが、精度を予測内に収めたい場合などには便利そうですね。
上のtechacademyからの引用ですが下記のように扱います。
BigDecimal b1 = new BigDecimal("3.1415");
BigDecimal b2 = new BigDecimal("9.9");
BigDecimal b3 = b1.multiply(b2);
すべての値をBigDecimalにして上記のようにメソッドで演算すれば目的の結果が得られるはずです。
ですがコードの目的は小数点1桁で四捨五入をして結果を表示したいという点ではないでしょうか?
weight,heightなどがdoubleと仮定して下記の式を小数点1桁で丸めるとすると下記の二つの例が考えられます。
calorie1. 10倍したものを四捨五入して、割りなおす。四捨五入にはMath.round命令を用います。
calorie2. 出力時に文字列にするのでその時点でString.formatする(仕様上、自動的に四捨五入されます)。
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));
}
}
参考 URL :
https://blog.apar.jp/program/8900/
http://hensa40.cutegirl.jp/archives/5620
Correct answer by Kouki.W on September 1, 2021
calorie
に対して BigDecimal で setScale をしているにもかかわらず、四捨五入されずに小数点以下5桁くらいまで表示されてしまっています。
質問されている事項の原因は、出力対象にしている calorie
は double
型であり、 BigDecimal
型として宣言している bd
は計算過程に一切関与していないためです。
// 表示対象として利用しているのは bd(BigDecimal) でなく calorie(double)
String msg0 = calorie + "cal";
代わりに、ここで calorie
の値を BigDecimal
に変換して利用します。
BigDecimal bd = new BigDecimal(calorie);
bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);
// 表示対象は calorie の値を BigDecimal型に変換したもの
String msg0 = bd.toString() + "cal";
ちなみに今回のように出力を整形したいだけの場合は、(BigDecimal
に変換するのではなく) double
型変数の値に対して String.format()
で書式文字列f
を適用するのが自然かなと思います。
String msg0 = String.format("%.1fcal", calorie);
Answered by DEWA Kazuyuki - 出羽和之 on September 1, 2021
回答していただきありがとうございます。
Math.round
を使ってみた結果、少数1桁で表示させることができました。
System.out.println
が上手く噛み合わなかったので、その部分は使いませんでした。原因として、最後のほうに
String msg0 = calorie + "cal";
calorieForm.setText(msg0);
を用いてtexitviewに反映されるようにしてあるかなと考えています。全然違っていたらすみません。
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);
Answered by yuki yuki on September 1, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP