diff --git a/src/main/java/info/istlab/Zemi01/NumericDemo.java b/src/main/java/info/istlab/Zemi01/NumericDemo.java index f87aa4b..21109a5 100644 --- a/src/main/java/info/istlab/Zemi01/NumericDemo.java +++ b/src/main/java/info/istlab/Zemi01/NumericDemo.java @@ -3,7 +3,7 @@ public class NumericDemo { public static void main(String[] args) { // ランチャーを起動する場合 - String[] opts = { "IEEE754view", "Lagrange", "RegLine" }; + String[] opts = { "IEEE754view", "Lagrange", "RegLine", "NormalDistribution" }; Launcher.show(opts, "info.istlab.Zemi01.numeric"); } } diff --git a/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java b/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java new file mode 100644 index 0000000..d7638e9 --- /dev/null +++ b/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java @@ -0,0 +1,278 @@ +package info.istlab.Zemi01.numeric; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Random; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import info.istlab.Zemi01.Launcher; +import info.istlab.Zemi01.miuramath.Ttest; + +/** + * 正規分布、ガウス分布 + */ + +public class NormalDistribution extends JPanel implements MouseListener, MouseMotionListener { + + private static final long serialVersionUID = -919448575666487391L; + public static JFrame jf; + + /** + * @param args + */ + public static void main(String[] args) { + jf = new JFrame("正規分布、ガウス分布"); + jf.getContentPane().add(new NormalDistribution()); + jf.pack(); + jf.setVisible(true); + jf.setLocation(Launcher.centerOfScreen(jf.getSize())); + + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + System.out.println("正規分布、ガウス分布 "); + System.out.println("つかいかた:(1)右クリックで、点を追加 (2)左ドラッグで、点移動 or グラフ移動 (3) 点の上で右クリックすると、点が消えます。"); + + } + + Point2D offset; + + ArrayList points; + Dimension dim; + Point2D pointingPmath; + Point2D pressP; + int psize = 10; + + public Dimension getPreferredSize() { + return dim; + } + + // 平均と分散 + double xavg = 0; + double xvarp = 1; + + /** + * ガウス関数、ただし、μとσ^2は、xavg, xvarp から計算する + * + * @param x + * @return + */ + public double gauss_function(double x) { + double d1 = 1.0 / Math.sqrt(2 * Math.PI * xvarp); + double d2 = Math.exp(-Math.pow(x - xavg, 2) / (2 * xvarp)); + double ret = d1 * d2 * 10000; + System.out.println(ret); + return ret; + } + + /** + * 点のx座標から、ガウス関数のパラメータ μとσ^2は、xavg, xvarp を更新する + */ + public void updateNormDist() { + double[] dat = new double[points.size()]; + int i = 0; + for (Point2D p : points) { + dat[i] = p.getX(); + i++; + } + // 平均値を更新する + xavg = Ttest.avg(dat); + // 標準偏差を更新する + xvarp = Ttest.varp(dat); + System.out.println("μ " + xavg + " σ^2 " + xvarp); + + } + + public NormalDistribution() { + offset = new Point2D.Double(0, 100); + + points = new ArrayList(); + dim = new Dimension(500, 400); + addMouseListener(this); + addMouseMotionListener(this); + + Random rand = new Random(); + for (int i = 0; i < 7; i++) { + int randx = rand.nextInt(-40, 40); + int randy = rand.nextInt(-10,0); + points.add(new Point2D.Double(randx, randy)); + } + setBackground(Color.white); + setForeground(Color.black); + } + + public void paint(Graphics g) { + paintComponent(g); + } + + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHints(rh); + + // g2d.setBackground(Color.white); + // g2d.setColor(Color.black); + g2d.clearRect(0, 0, getWidth(), getHeight()); + + paintGrid(g2d); + + for (Point2D p : points) { + paintPoint(g2d, p); + } + + if (pointingPmath != null) { + g2d.setColor(Color.red); + paintPoint(g2d, pointingPmath); + } + + updateNormDist(); + g2d.setColor(Color.blue); + paintRegLine(g2d); + + g2d.setColor(Color.blue); + g2d.drawString("μ = " + String.valueOf(xavg), (int) (-getWidth() / 2 + 10 - offset.getX()), + (int) (-getHeight() / 2 + 20 - offset.getY())); + g2d.drawString("σ = " + String.valueOf(Math.sqrt(xvarp)), (int) (-getWidth() / 2 + 10 - offset.getX()), + (int) (-getHeight() / 2 + 38 - offset.getY())); + g2d.drawString("σ^2 = " + String.valueOf(xvarp), (int) (-getWidth() / 2 + 10 - offset.getX()), + (int) (-getHeight() / 2 + 56 - offset.getY())); + } + + public void paintGrid(Graphics2D g2d) { + g2d.setColor(new Color(230, 230, 230)); + + g2d.translate(getWidth() / 2 + offset.getX(), getHeight() / 2 + offset.getY()); + // System.out.println(g2d.getTransform().getTranslateX()+" + // "+g2d.getTransform().getTranslateY()); + + for (int i = 0; i < getWidth(); i += 20) { + g2d.drawLine(i, -getHeight(), i, getHeight()); + g2d.drawLine(-i, -getHeight(), -i, getHeight()); + } + for (int i = 0; i < getHeight(); i += 20) { + g2d.drawLine(-getWidth(), i, getWidth(), i); + g2d.drawLine(-getWidth(), -i, getWidth(), -i); + } + g2d.setColor(Color.black); + g2d.drawLine(0, getHeight() * 3, 0, -getHeight() * 3); + g2d.drawLine(-getWidth() * 3, 0, getWidth() * 3, 0); + + // g2d.translate(-(getWidth()/2+offset.getX()), -(getHeight()/2+offset.getY())); + } + + public void paintPoint(Graphics2D g2d, Point2D p) { + g2d.fillOval((int) (p.getX() - psize / 2), + (int) (-(p.getY() + psize / 2)), psize, psize); + // g2d.drawString(String.valueOf(num), (int)p.getX()+10, (int)p.getY()); + } + + public void paintRegLine(Graphics2D g2d) { + Point2D prep = null; + for (double x = -getWidth() / 2 - offset.getX(); x < getWidth() / 2 - offset.getX(); x += 1.0) { + Point2D p1 = math2scr(new Point2D.Double(x, gauss_function(x))); + if (prep == null) + prep = p1; + g2d.drawLine((int) p1.getX(), (int) p1.getY(), (int) prep.getX(), (int) prep.getY()); + prep = p1; + } + } + + public Point2D scr2math(Point2D p) { + double x = p.getX(); + double y = p.getY(); + x = x - offset.getX() - getWidth() / 2; + y = y - offset.getY() - getHeight() / 2; + y = -y; + // System.out.println("scr2math "+x+", "+y); + return new Point2D.Double(x, y); + } + + public Point2D math2scr(Point2D p) { + return new Point2D.Double(p.getX(), -p.getY()); + } + + public void mouseClicked(MouseEvent e) { + if (e.getButton() == 3) { + Point2D pointing = findPointing(e.getPoint()); + if (pointing == null) + points.add(scr2math(e.getPoint())); + else { + if (points.size() > 2) + points.remove(pointing); + } + repaint(); + } + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public Point2D findPointing(Point2D mp) { + Point2D nearest = null; + Point2D mPmath = scr2math(mp); + for (Point2D p : points) { + if (mPmath.distance(p) < 8) { + nearest = p; + } + } + return nearest; + } + + public void mousePressed(MouseEvent e) { + scr2math(e.getPoint()); + pressP = e.getPoint(); + Point2D pressPmath = scr2math(pressP); + Point2D nearest = null; + for (Point2D p : points) { + if (pressPmath.distance(p) < 8) { + nearest = p; + } + } + pointingPmath = nearest; + repaint(); + } + + public void mouseReleased(MouseEvent e) { + pointingPmath = null; + repaint(); + } + + public void mouseDragged(MouseEvent e) { + if (pointingPmath != null) { + pointingPmath.setLocation(scr2math(e.getPoint())); + repaint(); + } else { + // e.translatePoint((int)offset.getX(), (int)offset.getY()); + offset.setLocation(offset.getX() + (e.getPoint().getX() - pressP.getX()), + offset.getY() + (e.getPoint().getY() - pressP.getY())); + pressP = e.getPoint(); + repaint(); + } + } + + public void mouseMoved(MouseEvent e) { + scr2math(e.getPoint()); + pressP = e.getPoint(); + Point2D pressPmath = scr2math(pressP); + Point2D nearest = null; + for (Point2D p : points) { + if (pressPmath.distance(p) < 8) { + nearest = p; + } + } + pointingPmath = nearest; + repaint(); + } + +}