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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

1258閲覧

三角形の直角、鋭角、鈍角の判定に間違いが発生する件。

ogiogimaru

総合スコア39

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2020/05/01 14:58

編集2020/05/01 15:02

本来なら直角と判定される値でも、プログラムで計算させると直角判定されません。(鈍角判定になります。)

import java.util.Scanner; public class ClassifyingToys{ public static void main(String[] args){ Scanner scan = new Scanner(System.in); double[] array = new double[3]; for (int i = 0 ; i < 3 ; i++) { array[i] = scan.nextDouble(); } double result = array[2]*array[2] - array[0]*array[0] - array[1]*array[1]; if(result < 0){ System.out.println(" : acute-angled"); }else if(result == 0){ System.out.println(" : right-angled"); }else{ System.out.println(" : obtuse-angled"); } } }

入力と出力は以下の通りです。
0.03 0.04 0.05 //入力
: obtuse-angled //出力

ただ、以下の値を入力したときは正常に判定されました。
3 4 5
: right-angled

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

コンピュータが扱う2進数では、ほとんどの10進数の小数を正確に表現できません。分母が2の累乗になるような既約分数(1/2,3/4など)以外は誤差が生じます。この辺の詳細は→double,float型とBigDecimalクラスは何がどう違うのですか?
0.03,0.04,0.05をdoubleに変換した時点で誤差が生じており、それぞれの2乗計算ではその誤差が累積するため、直角になる条件である「引き算の結果がちょうど0」は満たせません。整数と一致するdoubleであれば誤差が生じないので成立しますが。
10進数の計算を正確に行いたいなら、BigDecimalを使うなどの方法になります。

java

1import java.util.Scanner; 2import java.math.BigDecimal; 3 4public class ClassifyingToys{ 5 public static void main(String[] args){ 6 Scanner scan = new Scanner(System.in); 7 8 BigDecimal[] array = new BigDecimal[3]; 9 for (int i = 0 ; i < 3 ; i++) { 10 array[i] = new BigDecimal(scan.next()); 11 } 12 int result = array[2].pow(2).compareTo(array[0].pow(2).add(array[1].pow(2))); 13 if(result < 0){ 14 System.out.println(" : acute-angled"); 15 }else if(result == 0){ 16 System.out.println(" : right-angled"); 17 }else{ 18 System.out.println(" : obtuse-angled"); 19 } 20 } 21}

追記:改めて調べてみたら、Scannerで直接BigDecimalを取得できたので変更

java

1import java.util.Scanner; 2import java.math.BigDecimal; 3 4public class ClassifyingToys{ 5 public static void main(String[] args){ 6 Scanner scan = new Scanner(System.in); 7 8 BigDecimal[] array = new BigDecimal[3]; 9 for (int i = 0 ; i < 3 ; i++) { 10 array[i] = scan.nextBigDecimal(); 11 } 12 int result = array[2].pow(2).compareTo(array[0].pow(2).add(array[1].pow(2))); 13 if(result < 0){ 14 System.out.println(" : acute-angled"); 15 }else if(result == 0){ 16 System.out.println(" : right-angled"); 17 }else{ 18 System.out.println(" : obtuse-angled"); 19 } 20 } 21}

投稿2020/05/01 15:05

編集2020/05/02 01:53
swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

既に回答が付いている通りですが、、

float, doubleなどの浮動小数点を扱う場合、 == での比較の使用は限定的になるべきです。ある程度の誤差を見込むものです。
例えば、 (その範囲を 0.00001 とすれば)

if (result > 0.00001) { // 正の数字 } else if (result < -0.00001) { // 負の数字 } else { // 0と見なす }

となります。

投稿2020/05/02 01:45

pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

判定を int で行うようにした版を作ってみました。
入力された値をすぐに ParseDouble しないで、 String で保持し、
3つの数を捜査して 小数点をすべてブラして long 値にしてから 三角形の角度判定をするようにしています。

java

1import java.util.Scanner; 2 3public class Main { 4 public static void main(String[] args) { 5 Scanner scan = new Scanner(System.in); 6 String[] str_array = new String[3]; 7 for (int i = 0; i < 3; i++) { 8 str_array[i] = scan.next(); 9 } 10 check_triange(str_array); 11 String[] TESTS = { 12 "3 4 5", 13 "0.003 0.004 0.005", 14 "300 400 500", 15 "5 12 13", 16 "0.005 0.012 0.013" 17 }; 18 for (String line : TESTS) { 19 check_triange(line.split(" ")); 20 } 21 } 22 23 static void check_triange(String[] str_array) { 24 str_array = remove_shousuu(str_array); 25 long[] array = new long[3]; 26 for (int i = 0; i < 3; i++) { 27 System.out.print(str_array[i] + " "); 28 array[i] = Long.parseLong(str_array[i]); 29 } 30 System.out.println(); 31 32 long result = array[2] * array[2] - array[0] * array[0] - array[1] * array[1]; 33 System.out.println("result:" + result); 34 if (result < 0) { 35 System.out.println(" : acute-angled"); 36 } else if (result == 0) { 37 System.out.println(" : right-angled"); 38 } else { 39 System.out.println(" : obtuse-angled"); 40 } 41 } 42 static String[] remove_shousuu(String strs[]) { 43 int max_shousuu_len = 0; 44 for (String s : strs) { 45 int pos = s.indexOf("."); 46 if (pos >= 0) { 47 int len = s.length() - pos; 48 if (max_shousuu_len < len) { 49 max_shousuu_len = len; 50 } 51 } 52 } 53 54 if (max_shousuu_len == 0) { 55 return strs; 56 } 57 58 String padding_zeors = ""; 59 for (int i = 0; i < max_shousuu_len; i++) { 60 padding_zeors += "0"; 61 } 62 for (int i = 0; i < strs.length; i++) { 63 String int_s = ""; 64 String shousuu_s = ""; 65 String s = strs[i]; 66 int pos = s.indexOf("."); 67 if (pos < 0) { 68 int_s = s; 69 shousuu_s = ""; 70 } else { 71 int_s = s.substring(0, pos); 72 shousuu_s = s.substring(pos + 1); 73 } 74 shousuu_s = (shousuu_s + padding_zeors).substring(0, max_shousuu_len - 1); 75 strs[i] = int_s + shousuu_s; 76 } 77 return strs; 78 } 79}

実行例
イメージ説明

参考情報

  • Java 浮動小数点数の誤差に立ち向かう

https://qiita.com/kamikenta/items/084426d7d17efd23019d

投稿2020/05/03 04:45

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問