Javaで再現する電卓の平方根処理につまづいています

このQ&Aのポイント
  • Javaで文具店で1000円くらいで売っているような電卓を再現しようとしているものです。平方根のボタンを押したときの処理でつまづいています。
  • Windowsの電卓と違い、自分のコードで平方根を計算すると0.99999999998と表示され、1に収束しません。どのようにすれば1に収束するようにすることができるでしょうか?
  • 質問内容について詳しく説明しています。ボタンの処理や表示桁数について触れており、質問の要点をまとめています。
回答を見る
  • ベストアンサー

java 電卓 平方根

こんにちは。趣味でプログラミングをしているものです。 さっそくですが質問させていただきます。 Java で文具店で1000円くらいで売っているような電卓を再現 しようとしているのですが 平方根のボタンを押したときの処理でつまづいています。 3 を入力して平方根のボタンを押すと以下のサイトに表示されている限りにおいては 同じ数値になります。 http://ja.wikipedia.org/wiki/3%E3%81%AE%E5%B9%B3%E6%96%B9%E6%A0%B9 ここで質問の内容について説明させていただきます。 Windows に標準で付属している電卓では 0.5 を入力して平方根のボタンを押し続けると 最後には 1 が表示されます。 ですが、以下に示す自分のコードだと 0.99999999998 と表示されてその後 平方根のボタンを押し続けても同じ結果になります。 0.99999999998 で収束しているのだと思いますが、 (自分の作った電卓では小数点以外の数字は12個表示されるようになっています。) 1 に収束するようにするには、 以下に示す メソッドsqrt 内の計算部分の 割り算のスケールの指定とかを変えれば うまくいくのでしょうか? ----------------------------------------------- 平方根のボタンを押したときの処理です。 case CalculatorEvent.TYPE_SQRT : if( negativeflag ) { if( ! display.showBigMinus ) showNumString = showNumString.substring( 1 ); } result = sqrt( new BigDecimal( showNumString ) ); //test statement System.out.println( "from 1446 : " + result.toString() ); result = result.setScale( 32, RoundingMode.HALF_UP ); showNumString = result.toString(); //test statement; System.out.println( "sqrt result : " + showNumString ); // . . . . //以下おもに端数を表示桁数に丸めて、 //負の値の平方根を求めたときは //絶対値の平方根を求めて表示 // エラーであるマークも表示 // 呼び出し元に例外を投げる // 呼び出した側で例外を受け取ると // 電卓のボタンを入力できないようにする ----------------------------------------------- 上記コード test statement は以下の出力結果になると 以後 平方根のボタンを押しても同じ結果が出力されます。 from 1446 : 0.9999999999899999999999499999999994999999999937499999999125000000078125 sqrt result : 0.99999999998999999999995000000000 ------------------------------------------------ 上記コード中のメソッド sqrt です。 private BigDecimal sqrt( BigDecimal value ) { BigDecimal two = new BigDecimal( "2" ); BigDecimal x = value.divide( two ); BigDecimal last_x = BigDecimal.ZERO; BigDecimal gap = x.subtract( last_x ); BigDecimal range = BigDecimal.ONE.movePointLeft( 64 ); BigDecimal t; while( gap.compareTo(range) > 0 ) { last_x = new BigDecimal( x.toString() ); //t = value.divide( x, 64, BigDecimal.ROUND_DOWN ); //test statement t = value.divide( x, 64, RoundingMode.HALF_EVEN ); // x = x.add( t ).divide( two ); gap = x.subtract( last_x ).abs(); } return x; } ----------------------------------------------- 長文になりもうしわけありませんが、 ごぞんじのかた、教えていただけないでしょうか? よろしくお願いします。

noname#173931
noname#173931
  • Java
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • web2525
  • ベストアンサー率42% (1219/2850)
回答No.1

>0.5 を入力して平方根のボタンを押し続けると >最後には 1 が表示されます 数学的に言うと X<1の時√X=1になる事は在り得ません 限りなく1に近づくことはあってもX<1の時√X<1です >自分の作った電卓では小数点以外の数字は12個表示されるようになっています 精度にこだわる計算を行うのであれば 0.9999999999999…=1 が計算結果として表示されるのはまずいのではないでしょうか?

noname#173931
質問者

お礼

さっそく回答していただきありがとうございます。 数学的な見解を示して頂きありがたいのですが、 自分の電卓はこのとおりでもよいのかと思えますが、 回答していただけたついでといっては失礼かもしれませんが、 もう少し教えていただけないでしょうか (1) 数学の授業で極限の考え方というものがあったと思うのですが 極限ではやはり1に近づくのではないでしょうか? (2) Windows 標準の電卓ではどのような処理を経て、 1 が表示されるようになっているのでしょうか? ご存知であれば、教えていただけないでしょうか? よろしくお願いします。

関連するQ&A

  • Java 電卓を作っているのですが・・・

    こんにちは。 趣味でプログラミングをしているものです。 Java で電卓を再現しようとしていて、 コーディングが終わり動作を確認しているのですが、 わからないところがあるので質問させていただきました。 よろしくおねがいします。 平方根を求めるときなのですが、3や5などはある程度正確に求められている と思うのですが、 平方根を求めたとき整数になるもの 例えば9などは小数のまま表示されてしまいます。 電卓で表示され得るすべての実数について平方根を求めるには ニュートン法がよいと思うのですが・・・ 二点ほど質問させていただきます。 ------------------------------------ 質問A まず、BigDecimal型の平方根を求めて、 その toString() から得られた文字列を メソッドvalidControl( String value ) に渡すのですが その冒頭で末尾から先頭方向に続く'0' の列を取り除きたいのですが そのために、変数の中身をみてみたのがこの質問の下部のほうにある (ア) (イ) です。 sqrt(() などの演算結果でえられた文字列のうち 信頼できる範囲以下の文字列を validControl で切り取りたいのですが プロが実際に電卓を作るとしたら、 どのような処理になるのでしょうか? ------------------------------------ 質問B 平方根を求めるメソッドsqrt 内で二分法の処理では 除算のスケールを 64 に指定していますが、 実行結果(ア)(イ)の文字列の長さが異なるのは なぜでしょうか? ------------------------------------ private BigDecimal sqrt( BigDecimal value ) { BigDecimal two = new BigDecimal( "2" ); BigDecimal x = value.divide( two ); BigDecimal last_x = BigDecimal.ZERO; BigDecimal gap = x.subtract( last_x ); BigDecimal range = BigDecimal.ONE.movePointLeft( 64 ); BigDecimal t; while( gap.compareTo(range) > 0 ) { last_x = new BigDecimal( x.toString() ); //t = value.divide( x, 64, BigDecimal.ROUND_DOWN ); //(イ) //test statement t = value.divide( x, 64, RoundingMode.UP ); // (ア) // x = x.add( t ).divide( two ); gap = x.subtract( last_x ).abs(); } return x; } -------------------------------------- private String validControl( String value ) throws KETAException { String retstring = ""; boolean overflag = false; int idx1 = value.indexOf( '.' ); int gap = 0; int seisu_length = 0; // 整数部分の文字列の長さ int len = value.length(); int start = len-1; int idx2 = start; System.out.println( "(0)" + value ); System.out.println( "(1)" + String.valueOf( start ) ); while( value.charAt( idx2 ) == '0' ) { idx2 --; } if( idx2 != start ) { value = value.substring( 0, idx2 + 1 ); len = value.length(); } System.out.println( "(2)" +String.valueOf( idx2 ) ); // 以下省略 -------------------------------------- (ア) を実行したときの結果 (0) 3.000000000000000000000000000000000000 00000000000000000000000000000546875 (1)72 (2)72 --------------------------------------- (イ) を実行したときの結果 (0) 2.999999999999999999999999999999999999 999999999999999999999999999996875 (1)70 (2)70 -------------------------------------- 長文になり申しわけありませんが ご存知のかた教えていただけないでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • 平方根 ニュートン法について

    こんにちは。趣味でプログラミングをしているものです。 さっそくですが、質問させていただきます。 Javaで文具店などで1000円くらいで市販されている 電卓を再現しようとしているのですが、 質問させていただきたいのは、 平方根の計算についてです。 -------------------------------------------- まずは以下のメソッドのコードを見ていただきたいのですが・・・ このメソッドを用いて3の平方根を求めてみました。 private static BigDecimal sqrt( BigDecimal value ) { BigDecimal two = new BigDecimal( "2" ); BigDecimal x = value.divide( two ); BigDecimal last_x = BigDecimal.ZERO; BigDecimal gap = x.subtract( last_x ); BigDecimal range = BigDecimal.ONE.movePointLeft( 11 );//(a) //int cnt = 0;//(b) BigDecimal t; while( gap.compareTo(range) > 0 )//(c) //while( cnt < 20 )//(d) { last_x = new BigDecimal( x.toString() ); t = value.divide( x, 64, BigDecimal.ROUND_DOWN ); x = x.add( t ).divide( two ); gap = x.subtract( last_x );//(e) //cnt ++; //(f) } return x; } (a)(c)(e) を用いて実行すると 1.732142857142857142857・・・ と小数部分の142857 が循環する値になりました。 (a)(c)(e) をコメントアウトして (b)(d)(f) を用いて実行すると 1.732050807568877293527446341505872366942805253 810380628055806979425806427001953125 とwikipedia の「3の平方根」の記事の値と 記述されている範囲では同じ値が得られました。 -------------------------------------------- そこで質問なのですが、 (1) (a) (c) (e) を用いた場合には、正しい値を得られないのでしょうか? 条件に設定する値などを変えてもだめなのでしょうか? (2) 自分が作っている電卓では12桁の表示を予定しているのですが その場合、メソッド sqrt ないの cnt は while ループ内で いくつまで、インクリメントすればよいのでしょうか? (3) インターネットで調べたこのアルゴリズムは 「ニュートン法」だそうですが、 y = x^2 - C の グラフ、接線などを書いてみて ある程度理解できたのですが、 http://cpplover.blogspot.jp/2010/11/blog-post_20.html 上記サイトではこのアルゴリズムは バビロニア人の方法(Babylonian method) というものだそうですが、 バビロニア人は二次関数の微分はわかっていた、 ということでしょうか? -------------------------------------------- ご存知のかた、教えていただけないでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • 電卓アプリで%キーの計算プログラムについて

    現在、Androidのアプリ作成の勉強に励んでいます。 まず、手始めに電卓アプリを作りながら学んでいますが、 電卓キーの「%キー」をClickした時の計算プログラムがどうしても考えつきません。 できれば、BigDecimalメソッドを使って「%キー」の計算をさせることができればと 思っています。 doCalcというメソッドを作ってその中に計算プログラムを書いていて doCalcメソッドの中身(足し算、引き算、乗算、除算についての計算プログラム)についての計算プログラム)は下記のとおりです。 是非、ご教授いただければ助かります。 またBigDecimalメソッドを使わず他のやりかたでも結構ですので、参考にご教授いただければ幸いです。 宜しくお願いいたします。 //strResult=入力中の数値 //strTemp=入力が完了した数値と計算結果で共有 private String doCalc() { BigDecimal bd1=new BigDecimal(strResult); BigDecimal bd2=new BigDecimal(strTemp); BigDecimal result=BigDecimal.ZERO; switch(operator) { case R.id.KeypadAdd: result=bd1.add(bd2); break; case R.id.KeypadSub: result=bd1.subtract(bd2); break; case R.id.KeypadMulti: result=bd1.multiply(bd2); break; case R.id.KeypadDiv: if(!bd2.equals(BigDecimal.ZERO)){ result=bd1.divide(bd2, 12, 3); }else{ Toast toast=Toast.makeText(this,R.string.toast_div_by_zero,1000); toast.show(); } break; } if(result.toString().indexOf(".")>=0){ return result.toString().replaceAll("\\.0+$|0+$",""); }else{ return result.toString(); } }

  •  分数乗の平方根の書き方と開き方

    x^1/y (xの1/y乗)を平方根になおすと、どういう書き方になりますか? そして、平方根にした時の、開き方を教えてください。 問題としては、 x^8=(100÷67.704)-1 x=(100÷67.704)^1/8 -1 x=4.996 2行目まではわかるのですが、その後の計算のしかたと、(多分√になおすのでしょうが)がどうしてもわかりません。 ちなみに、(100÷67.704)の答えを、電卓の√を3回押した後に、1を引くと、4.996と答えが出るのですが、何故3回なのか理由がわからないです。 低レベルな質問で申し訳ありませんが、よろしくお願いいたします。

  • CCSCを使ったPICによる平方根(√)を含む計算方法について

    PICで平方根を含む計算を行いたいのですが、どうすればよいでしょうか? √2だと2^1/2で行けるだろうとやるとエラーが帰ってきます。 変数はすべてdoubleで宣言しているのですが、そこでエラーが帰ってきます。 ソースはこれです sqrt(1 - (x + dx) * (x + dx)) これをCCSCのコンパイラでコンパイルできるようにしたいです。 どう書けばよいでしょうか? わかる方よろしくお願いします

  • maximaによる平方根と自然対数の混在式について

     PCソフト関係なのですが、内容が数学かと考えてこのカテゴリで質問させていただきます。  maximaによって平方根と自然対数が混在した式を解くには(たとえば log(x-1)/sqrt(x+1)=yでxを出す式 など)どのような関数を使えばいいのでしょうか? solveを使ってもうまく答えが出てきません。 よろしくお願いします。

  • 関数の極限の問題ですが

    解けないのでご教授お願いします。 lim[x→-∞]{(sqrt(x^2+x+1))-(sqrt(x^2-x+1))}です(sqrtは平方根) よろしくお願いします。

  • 積分できない!?

    こんにちは、 積分を習っているんですが、なかなか解けません! 助けてください! 問題は Integral dx/sqrt(37+2x+x^2)です ちなみにSqrtは平方根です。 よろしくお願いします

  • 極々簡単な電卓の作成

    とても初歩的な質問で恐縮なのですが、VBAで電卓を作ろうと思っています。 加減乗除くらいの機能で、ボタン配置して、入力式は消えずにエクセルの任意のセルに表示させて、計算結果も任意のセルに表示。 このような電卓を作ろうと思っているのですが、 例えば「1」のボタンを押すと Cells(1, 1).Value = Cells(1, 1).Value & 1 これをそれぞれのボタンについて繰り返して・・・そこで行き詰まっています。 本当に初歩的だと思うのですが、=が押されたときや計算の記述が全くわかりません。 どなたかアドバイスいただけると幸いです。

  • javaで電卓を作りたいのですが(Swing

    こんにちは。プログラミング初心者なのでどうかご助言願います。 javaのSwing(JFRAME)で電卓を作ろうとしているのですが、一応動作はするのですが連続計算がうまくいきません たとえば66(画面表示は66)*3(画面表示は3)-(画面表示は198)8(画面表示は8)=190 という計算をさせたいのですが、途中でうまくいってないみたいで 最終的な答えが58、という答えが出てしまいます。(途中はきちんと198と表示されます) 下のメソッドのどこが間違っているかご指摘頂けるとありがたいです int val =0; int val0=0; String op = null; //数字 public void numberreturn(int i){ val=val*10+ i; resultTextField.setText((new Integer(val)).toString()); } //演算子 public void calculate(String x){ if(op==null){ if(val0!=0){ op=x; }else{ val0=val; val=0; op=x;} }else if(val==0){ op=x; }else if(val0!=0){ returning(val0,val,op); op=x; }else{ val0=val; val=0; op=x; } } //結果表示 public void ansreturn(int i){ resultTextField.setText((new Integer(i)).toString()); } //計算を行う関数 public void returning (int i,int j,String x){ if(x!=null){ int k; if(x=="plus"){ k=i+j; } else if(x=="minus"){ k=i-j; } else if(x=="mult"){ k=i*j; } else{ try{ k=i/j; }catch(Exception e){ k=0; } } i=k; ansreturn(i); j=0; x=null; }else{ j=0; x=null; } } ボタンのほうは一応こんな感じです private void minusButtonActionPerformed(java.awt.event.ActionEvent evt) { calculate("minus"); } private void equallButtonActionPerformed(java.awt.event.ActionEvent evt) { returning(val0,val,op); } よろしくお願いします

    • ベストアンサー
    • Java

専門家に質問してみよう