double 型や, sin, cos などの関数の扱い

目次 携帯Javaのページ

最後の更新は次の時刻以降のはず. Time-stamp: "2003/09/05 Fri 18:11 hig"

円を書くのにも, sin, cos を使いますが, i-appli の java では, sin, cos 関数はないので, 値を覚えておくしかありません.

また, 覚えておくと言っても, double 型がないので, sin q=x/100000 のような分数だと思って, 整数 x を覚えることにします. これに演算をするときは, 順序をよく考えなくてはいけません. int の間の演算では, ( 10 * 100 ) / 1000=1000/1000=1, 10 * (100 / 1000) = 10 * 0 = 0 です. 一般に, オーバーフローしない範囲で, 割り算は最後に1回だけ行う, ようにするのがいいでしょう.

/*
  double の扱い. sin, cos の作成
  hig
  Time-stamp: "2003/01/20 Mon 22:01  hig"
 */


import com.nttdocomo.ui.*;
import com.nttdocomo.util.*;

public class CanvasTable1 extends IApplication {

    /** 起動するときに呼ばれる メソッド. 必須. */
    public void start(){
	CircleCanvas cc=new CircleCanvas();
	Display.setCurrent(cc);

	Timer ti=new Timer();
	int interval=100;
	ti.setTime(interval);	// interval ミリ秒で発生するタイマー
	ti.setRepeat(true);	// 繰り返し発生するタイマー
	ti.setListener(cc);	// クラス cc の timerExpired を使用.
	ti.start();		// カウントダウン開始. 一時停止は, ti.stop();
    }



}


class CircleCanvas extends Canvas implements TimerListener{

    CircleCanvas(){
	if( getWidth() > getHeight() ){
	    radius=getHeight()/2;
	} else {
	    radius=getWidth()/2;
	}
    }


    public void paint(Graphics g){
	// g.lock();//画面をいったん固定(ダブルバッファリング)
	// 下の unlock とペアでアンコメントしてみよう.

	g.clearRect(0,0,getWidth(),getHeight());// 画面を消す

	for(int i=0; i < period ; i++){
	    /* (x1,y1) と (x2,y2) の間に線分をひく */
	    g.drawLine( radius + (radius * sin[ theta%period ]) /magfactor,//x1
			radius - (radius * cos[ theta%period ]) /magfactor,//y1
			radius + (radius * sin[ (theta+1)%period ]) /magfactor,//x2
			radius - (radius * cos[ (theta+1)%period ]) /magfactor//y2
			);
	    /*
	    g.drawLine( radius + radius * (sin[ i%period ] /magfactor) ,//x1
			radius - radius * (cos[ i%period ] /magfactor) ,//y1
			radius + radius * (sin[ (i+1)%period ] /magfactor),//x2
			radius - radius * (cos[ (i+1)%period ] /magfactor) //y2
			);
			だとどうなるかな
	    */



	}
	g.fillRect(radius + (radius * cos[ theta%period ]) / magfactor,
		   radius - (radius * sin[ theta%period ]) / magfactor,
		   4,4);
	
	// g.unlock(true);//画面を再度表示(ダブルバッファリング終了)
    }


    /** Timer が 0 になったとき呼ばれるメソッド
	implements TimerListner を宣言したらこれが必要 */
    public void timerExpired(Timer source){ 
	theta=(theta+1) % period;	// 角度を進め
	repaint();		// paint() を再度呼び出す.
    }



    int radius;


    /** 2pi に相当する 度 */
    private final int period=360; 
	
    private final int magfactor=100000;

// 100000.0*sin(n度) を長さ 360 の整数配列にしたもの
// 本当は, sin の始め90個から sin, cos すべてを簡単に計算できるはず.
    private final int sin[]={
    0,1745,3489,5233,6975,8715,10452,12186,13917,15643,
    17364,19080,20791,22495,24192,25881,27563,29237,30901,32556,
    34202,35836,37460,39073,40673,42261,43837,45399,46947,48480,
    49999,51503,52991,54463,55919,57357,58778,60181,61566,62932,
    64278,65605,66913,68199,69465,70710,71933,73135,74314,75470,
    76604,77714,78801,79863,80901,81915,82903,83867,84804,85716,
    86602,87461,88294,89100,89879,90630,91354,92050,92718,93358,
    93969,94551,95105,95630,96126,96592,97029,97437,97814,98162,
    98480,98768,99026,99254,99452,99619,99756,99862,99939,99984,
    100000,99984,99939,99862,99756,99619,99452,99254,99026,98768,
    98480,98162,97814,97437,97029,96592,96126,95630,95105,94551,
    93969,93358,92718,92050,91354,90630,89879,89100,88294,87461,
    86602,85716,84804,83867,82903,81915,80901,79863,78801,77714,
    76604,75470,74314,73135,71933,70710,69465,68199,66913,65605,
    64278,62932,61566,60181,58778,57357,55919,54463,52991,51503,
    49999,48480,46947,45399,43837,42261,40673,39073,37460,35836,
    34202,32556,30901,29237,27563,25881,24192,22495,20791,19080,
    17364,15643,13917,12186,10452,8715,6975,5233,3489,1745,
    0,-1745,-3489,-5233,-6975,-8715,-10452,-12186,-13917,-15643,
    -17364,-19080,-20791,-22495,-24192,-25881,-27563,-29237,-30901,-32556,
    -34202,-35836,-37460,-39073,-40673,-42261,-43837,-45399,-46947,-48480,
    -50000,-51503,-52991,-54463,-55919,-57357,-58778,-60181,-61566,-62932,
    -64278,-65605,-66913,-68199,-69465,-70710,-71933,-73135,-74314,-75470,
    -76604,-77714,-78801,-79863,-80901,-81915,-82903,-83867,-84804,-85716,
    -86602,-87461,-88294,-89100,-89879,-90630,-91354,-92050,-92718,-93358,
    -93969,-94551,-95105,-95630,-96126,-96592,-97029,-97437,-97814,-98162,
    -98480,-98768,-99026,-99254,-99452,-99619,-99756,-99862,-99939,-99984,
    -100000,-99984,-99939,-99862,-99756,-99619,-99452,-99254,-99026,-98768,
    -98480,-98162,-97814,-97437,-97029,-96592,-96126,-95630,-95105,-94551,
    -93969,-93358,-92718,-92050,-91354,-90630,-89879,-89100,-88294,-87461,
    -86602,-85716,-84804,-83867,-82903,-81915,-80901,-79863,-78801,-77714,
    -76604,-75470,-74314,-73135,-71933,-70710,-69465,-68199,-66913,-65605,
    -64278,-62932,-61566,-60181,-58778,-57357,-55919,-54463,-52991,-51503,
    -50000,-48480,-46947,-45399,-43837,-42261,-40673,-39073,-37460,-35836,
    -34202,-32556,-30901,-29237,-27563,-25881,-24192,-22495,-20791,-19080,
    -17364,-15643,-13917,-12186,-10452,-8715,-6975,-5233,-3489,-1745};
// 100000.0*cos(n度) を長さ 360 の整数配列にしたもの
    private final int cos[]={
    100000,99984,99939,99862,99756,99619,99452,99254,99026,98768,
    98480,98162,97814,97437,97029,96592,96126,95630,95105,94551,
    93969,93358,92718,92050,91354,90630,89879,89100,88294,87461,
    86602,85716,84804,83867,82903,81915,80901,79863,78801,77714,
    76604,75470,74314,73135,71933,70710,69465,68199,66913,65605,
    64278,62932,61566,60181,58778,57357,55919,54463,52991,51503,
    50000,48480,46947,45399,43837,42261,40673,39073,37460,35836,
    34202,32556,30901,29237,27563,25881,24192,22495,20791,19080,
    17364,15643,13917,12186,10452,8715,6975,5233,3489,1745,
    0,-1745,-3489,-5233,-6975,-8715,-10452,-12186,-13917,-15643,
    -17364,-19080,-20791,-22495,-24192,-25881,-27563,-29237,-30901,-32556,
    -34202,-35836,-37460,-39073,-40673,-42261,-43837,-45399,-46947,-48480,
    -49999,-51503,-52991,-54463,-55919,-57357,-58778,-60181,-61566,-62932,
    -64278,-65605,-66913,-68199,-69465,-70710,-71933,-73135,-74314,-75470,
    -76604,-77714,-78801,-79863,-80901,-81915,-82903,-83867,-84804,-85716,
    -86602,-87461,-88294,-89100,-89879,-90630,-91354,-92050,-92718,-93358,
    -93969,-94551,-95105,-95630,-96126,-96592,-97029,-97437,-97814,-98162,
    -98480,-98768,-99026,-99254,-99452,-99619,-99756,-99862,-99939,-99984,
    -100000,-99984,-99939,-99862,-99756,-99619,-99452,-99254,-99026,-98768,
    -98480,-98162,-97814,-97437,-97029,-96592,-96126,-95630,-95105,-94551,
    -93969,-93358,-92718,-92050,-91354,-90630,-89879,-89100,-88294,-87461,
    -86602,-85716,-84804,-83867,-82903,-81915,-80901,-79863,-78801,-77714,
    -76604,-75470,-74314,-73135,-71933,-70710,-69465,-68199,-66913,-65605,
    -64278,-62932,-61566,-60181,-58778,-57357,-55919,-54463,-52991,-51503,
    -50000,-48480,-46947,-45399,-43837,-42261,-40673,-39073,-37460,-35836,
    -34202,-32556,-30901,-29237,-27563,-25881,-24192,-22495,-20791,-19080,
    -17364,-15643,-13917,-12186,-10452,-8715,-6975,-5233,-3489,-1745,
    0,1745,3489,5233,6975,8715,10452,12186,13917,15643,
    17364,19080,20791,22495,24192,25881,27563,29237,30901,32556,
    34202,35836,37460,39073,40673,42261,43837,45399,46947,48480,
    50000,51503,52991,54463,55919,57357,58778,60181,61566,62932,
    64278,65605,66913,68199,69465,70710,71933,73135,74314,75470,
    76604,77714,78801,79863,80901,81915,82903,83867,84804,85716,
    86602,87461,88294,89100,89879,90630,91354,92050,92718,93358,
    93969,94551,95105,95630,96126,96592,97029,97437,97814,98162,
    98480,98768,99026,99254,99452,99619,99756,99862,99939,99984};

    int radius;
    int theta=0;



}

ここで, この配列 sin, cos は, J2SE の プログラム で作りました.

penguin15% javac TrigTable.java
penguin15% java TrigTable > table 
などとするんですね.

ちなみに, 標準でない MathFP というクラスライブラリを使うと, もう少し楽に小数を扱えます. 樋口による解説

課題

アナログ時計を作ろう. 世の中のアナログ時計って, 日時の表示があったり, 文字盤に絵が描いてあったり, 月齢計があったり, n時0分には楽隊が出てきて演奏したりするよね :)

ここでデジタル時計の例. クラス Calendar の API は, CLDC のドキュメントの中にあります.
/*
  日時の扱い.
  hig
  Time-stamp: "2002/11/27 Wed 22:23"
 */

import com.nttdocomo.ui.*;
import java.util.*;// Calendar を使う
import com.nttdocomo.util.*; // Timerを使う


public class DigitalClock1 extends IApplication {

    /** 起動するときに呼ばれる メソッド. 必須. */
    public void start(){
	ClockCanvas cc=new ClockCanvas();
	Display.setCurrent(cc);

	Timer ti=new Timer();
	ti.setTime(1000);	// 1000ミリ秒で発生するタイマー
	ti.setRepeat(true);	// 繰り返し発生するタイマー
	ti.setListener(cc);	// クラス cc の timerExpired を使用.
	ti.start();		// カウントダウン開始. 一時停止は, ti.stop();
    }



}


class ClockCanvas extends Canvas implements TimerListener{


    public void paint(Graphics g){
	Calendar c = Calendar.getInstance();

	g.clearRect(0,0,getWidth(),getHeight());// 画面を消す
	g.drawString( 	c.get(Calendar.HOUR) + "時" + 	
			c.get(Calendar.MINUTE) + "ふん" +
			c.get(Calendar.SECOND) + "秒くらいだよん" ,
			0,getHeight()/2);


    }


    public void timerExpired(Timer source){ 
	repaint();		// paint() を再度呼び出す.
    }
}



Copyright © 2002-2003 Saburo Higuchi. All rights reserved.
樋口三郎, http://www.math.ryukoku.ac.jp/~hig/ hig mail address