とあるフレームワークで計算するメソッドを通して計算させると、引数によって有効桁までのStringが戻り値として返されます。
そのStringの戻り値を使用して処理を分岐させたいのですが、幾分有効桁に問題があります。
(例)
String p_str1 = "100"
String p_str2 = "100.0"
このp_str1とp_str2を等しいとみなしたいのですが、愚直に末尾から順番に文字を取り出し、最後の桁が0の場合は切り捨て(直前が.ピリオドの場合はピリオドモ含めて)てするような方法しか思いつきません。
それ以外にp_str1とp_str2を等しいとみなす方法はないでしょうか?
よろしくお願いいたします。
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
No.5です。
有効桁という表現をしてしまいましたが、誤りです。
有効桁数を指定するものではなく、誤差の範囲を指定しています。
切捨ての桁数指定とでも言いますか...
頭から3桁とか指定桁しか見ないということではないということです。
つまり、
100.5
と
100
1000000000.5
と
1000000000
の両方で
prec = 0 で渡せば true が
prec = -1 で渡せば false が
返ってきます。
prec = -1 の場合、渡された値の差の絶対値が 約0.1 以下だったら true
それ以上ならば false を返ります。
丸め誤差と書いたのは、例えば差が0.1等の場合、浮動小数点型では厳密に表すことができないために、正しく比較されないという意味です。この場合は prec
の指定を大きくすることで解決することができます。
ちなみに
long だと
-9223372036854775808 ~ 9223372036854775807
double だと
-1.7976931348623157E308 ~ 1.7976931348623157E308
この範囲から外れる大きさの入力がありますか?
また有効桁数は何桁必要ですか?
値が上記範囲外で有効桁数が16~18桁以上必要であれば
BigDecimal を使うのがよいと思います。
この範囲内なら先に書いた方法でも対応できるかと思います。
No.6
- 回答日時:
>インプットデータの桁数変更はありえるためその場合は辛いところです。
桁数変更があり得るなら、そのようにコーディングすればよいだけですよね。
機械的には "100" と "100.0" は「異なる」ものなので、それを「等しい」とみなす方法については要件次第です。
ANo.5 の方の回答のように、有効桁数を折り込んだメソッドにすれば対応できそうに思われますが。
No.5
- 回答日時:
こんなんでどうですか?
public static void main(String[] args) {
String p_str1 = "100"
String p_str2 = "100.0"
System.out.println(eq(p_str1, p_str2, 0));
}
public static boolean eq(String s1, String s2, int prec){
double d1 = Double.valueOf(s1);
double d2 = Double.valueOf(s2);
return Math.abs(d1 - d2) < Math.pow(10, prec);
}
precに有効桁を指定します。
0なら小数点以下無視
-1なら少数第一位まで
-2なら少数第二位まで
ただし、浮動小数点演算なので丸め誤差があります。
回答が遅れまして申し訳ございません。
100と100.0に関しては問題ないですね。
しかし、インプットデータの桁数によっては、結構桁数が大きくなってしまうことがあります。
丸め誤差に関しては、現在のところはインプットデータの桁数は問題ない桁数ですが、将来的にそのままかどうかわかりません。
Math.powメソッドは今まで使用したことがありませんでしたので、勉強になりました。
ありがとうございます。
No.4
- 回答日時:
こういうのは正規表現使うとよかとです。
//正規表現で「.00…0」を除去して同じ文字かチェック(ざっと動作チェック済み)
Pattern p =Pattern.compile("\\.0+$"); //このパターンの正規表現を使う
String p_str1 = "100"
String p_str2 = "100.000"
//「.0…0」を取り除く。念のため両方の文字を変換している
String s1 = p.matcher(p_str1).replaceAll(""); //""に置換して取り除く
String s2 = p.matcher(p_str2).replaceAll(""); //
//チェック
if (s1.equals(s2)){
System.out.println("Equal");
} else{
System.out.println("Not Equal");
}
正規表現は「\.」「0+」「$」を組み合せたものです。
「\.」はピリオド(小数点)を表し、「0+」は0の繰り返し、
「$」はそこで文字が終了、ということになります。
つまり、小数点以下0だけが最後まで続く、となり、「.00…0」と一致します。
あとは、それと一致した部分(つまり「.00…」の部分)を空文字""で置換することで
除去してるわけです。
正規表現やそれを使うクラスはあまり詳しくないので、
他にもっと良いやり方があるかもしれないのですが…
まあ、何かの参考にでもなればと。
参考URL:http://www.hellohiro.com/regex.htm
回答が遅れまして申し訳ございません。
正規表現は不得意で、あまり知らなかったのですが、
かなりシンプルかつわかりやすく実装できますね。
古いJRE上での動作は考えていないので、問題ないです。
よい勉強になりました。
ありがとうございます。
No.3
- 回答日時:
/**
たま~にこういったのにマジレスすると、復習になっていいですね。
(Tigerにて動作確認済。)
*/
class AntiTacit{
static public void main(String... henkan){
String p_str1 = "100";
String p_str2 = "100.0";
System.out.println("変換前 " + p_str1 + " " + p_str2);
// 文字列から基本データ型の値を取得。
int p_str1_int = Integer.parseInt(p_str1);
double p_str2_d = Double.parseDouble(p_str2);
// 文字列からオブジェクトを生成直後にアンボクシング。
double p_str2_d_unb1 = new Double(p_str2);
double p_str2_d_unb2 = Double.valueOf(p_str2);
// 明示的にキャスト。
int p_str2_d_int = (int)p_str2_d;
int p_str2_d_unb1_int = (int)p_str2_d_unb1;
int p_str2_d_unb2_int = (int)p_str2_d_unb2;
// 数学関数を使用。
long p_str2_d_round = Math.round(p_str2_d);
// 4通りとも同じ結果となることを一気に判断。
if(p_str1_int == p_str2_d_int &&
p_str1_int == p_str2_d_unb1_int &&
p_str1_int == p_str2_d_unb2_int &&
p_str1_int == p_str2_d_round){
System.out.println("変換後その1" + p_str1_int + " " + p_str2_d_int);
System.out.println("変換後その2" + p_str1_int + " " + p_str2_d_unb1_int);
System.out.println("変換後その3" + p_str1_int + " " + p_str2_d_unb2_int);
System.out.println("変換後その4" + p_str1_int + " " + p_str2_d_round);
}else{
// もちろん、この行は実行されない。
assert false : "\n● p_str1とp_str2を等しいとみなしませんでした。●";
}
}
}
回答が遅れまして申し訳ございません。
頂きましたサンプルを色々と弄り回して動きを確認させていただきました。確かにできますね。
型変換の勉強になりました。
普段サボりがちであまりやらないところなので、理解が進みよい練習になりました。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 高校 有効数字計算 確定した値を含む 2 2023/01/18 06:03
- Visual Basic(VBA) VBAで時間(00:00形式)を積算(足し算)したい 1 2022/11/15 17:04
- 化学 有効数字の取り扱いについて 高校化学では、測定値同士の計算結果の有効数字は、測定値に合わせるようにな 4 2022/06/30 14:07
- 高校 高校化学、気体、温度の有効数字 3 2023/04/02 11:39
- Excel(エクセル) エクセルのマクロについて教えてください。 1 2023/02/11 13:29
- Access(アクセス) エクセルのマクロについて教えてください。 2 2023/02/03 16:07
- Visual Basic(VBA) VBAで最新のデータを別シートに転記する方法をお教えください。 3 2022/04/07 19:20
- 放射線治療・リハビリテーション リハビリ系のお仕事についてです。 将来、リハビリ系のお仕事につきたいと思っているのですが PT、OT 1 2022/05/21 20:31
- 物理学 この問題における抵抗r1とxってどのように考えれば良いのでしょうか?トルクはT=P2/ωsなのでP2 1 2022/06/19 18:46
- パチンコ・スロット パチンコの継続率について疑問なんですけど… 体感的な話ですが継続率って同じ数字でも抽選の仕方で違いま 5 2022/08/07 09:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
JAVAでCの関数ポインタのような...
-
【C#】フォームをなめらかに移動
-
Javaで電卓を作りたい
-
DataSet(DataTable)の使い方
-
三目並べ(Tick-Tack-Toe)をJav...
-
式の型は配列型で int に解決済...
-
java spring でエラーが出て困...
-
byte[]→int
-
コマンドライン引数 java
-
JSPのアルゴリズムで質問
-
javaでcsvファイル読込時の改行...
-
Javaのファイル名チェックについて
-
前日日付の取得
-
6桁の数字を重複なしでランダム...
-
C#でバブルソート
-
Stringの100と100.0を同一とみ...
-
SwingでJtableのヘッダ行が表示...
-
「配列定数は、イニシャライザ...
-
(Swing)JTextFieldを半角のみ入...
-
ダブルクォーテーションのrepla...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「配列定数は、イニシャライザ...
-
Javaで電卓を作りたい
-
式の型は配列型で int に解決済...
-
javaでカレンダー作成
-
JAVA エラー 式の開始が不正で...
-
JAVAでCの関数ポインタのような...
-
java spring でエラーが出て困...
-
6桁の数字を重複なしでランダム...
-
c# デリゲート関連の命名について
-
C++からC#のdllを参照する際、...
-
メインが含まれていません
-
(Swing)JTextFieldを半角のみ入...
-
DataSet(DataTable)の使い方
-
三目並べ(Tick-Tack-Toe)をJav...
-
JUnit4のアノテーションについて
-
初心者ですが、今javaで簡単な...
-
classを使って座標軸を求めるコ...
-
javaでcsvファイル読込時の改行...
-
C#で実行時にメソッドの返り値...
-
Java 初心者 int型の取り扱い方
おすすめ情報