2015年7月31日 星期五

生日悖論

生日悖論是考慮下面這個問題:假設一個班級有23個或23個以上的人,那麼至少有兩個人生日相同的機率大於50%,對於60或更多的人,至少有兩個人生日相同的機率大於99%,從引起邏輯角度來看生日悖論不是一種悖論,這邊的悖論是指這個數學事實與一般直覺相抵觸。


將問題重新整理一邊,假設一個班級有N個人,每個人生日的日期是隨機的(不考慮2/29),那麼至少有兩個人生日相同的機率是多少呢?
大約要多少人,至少有兩個人生日相同的機率才會大於50%呢?

看到這個問題一般的直覺會覺得說一年有365天,大概要50~100人以上才會讓至少有兩個人生日相同的機率大於50%吧,怎麼會只要23人呢,事實上解決這個問題可以用簡單的高中數學來想。

考慮此事件的補集:所有人生日都不同的機率
N個人生日皆不同的機率為1  * 364/365 * 363/365 * ... * (365-N+1)/365

用階層可表示為 365! /[(365^N)(365-N)!]

而至少有兩個人生日相同的機率就是 1-  365! /[(365^N)(365-N)!]

這個數字在N=20時大約是41%
N=23時會大於50%
N=30時約為70%
N在60以上的時候就會超過99%



一般會覺得生日相同不常見主要是因為只專注在生日跟自己相同的人
此時補集的機率就是(364/365)^N,這個數字會比至少兩人生日相同來的大非常多


不過一般來講真實世界的生日分佈並不是平均分佈的,這種非均衡的生日分佈問題則會是另一種數學問題,並且此問題也被解決了[Klamkin 1967]

其實很多數學跟生活上的問題不會如同直覺那樣簡單,在看到問題時不彷坐下來思考並想想問題是否有解,有時候得到的結論會跟自己想像的遠遠不同,相當有趣

[Java]計時器功能:Timer、TimerTask

使用定時或固定時間間隔有幾個方法
一個是Thread.sleep();

方法內填延遲的毫秒數就可以讓程式延遲後再執行

另一種就是使用Timer class
這個class的schedule方法有兩個變數以及三個變數
詳細的使用方法請見範例
範例有兩個class,將要執行的程式碼寫在繼承TimerTask的class裡面
然後使用Timer裡面你要用的方法就可以使用定時執行程式的功能了


import java.text.SimpleDateFormat;
import java.util.*;
public class TimerDemo {
 SimpleDateFormat sdf = new SimpleDateFormat("hh時mm分ss秒 yyyy年MM月dd日");
    public static void main(String[] args) {
        TimerDemo timerDemo = new TimerDemo();
        System.out.println("方法一示範");
        timerDemo.testScheduleDelay();
        System.out.println("方法二示範");
        timerDemo.testScheduleDelayAndPeriod();
        System.out.println("方法三示範");
        timerDemo.testScheduleDateAndPeriod();
   }
    
    void testScheduleDelay(){
        Timer timer = new Timer();
        System.out.println("延遲時間:3秒");
        System.out.println("現在時間:" + sdf.format(new Date()));
        // schedule(TimerTask task, long 延遲時間)
        timer.schedule(new DateTask(), 3000);
        
        try {
            Thread.sleep(10000);
        }
            catch(InterruptedException e) {
        }
        timer.cancel();
        System.out.println("結束時間:" 
            + sdf.format(new Date()) + "\n");
    }
    
    void testScheduleDelayAndPeriod(){
        Timer timer = new Timer();
        System.out.println("延遲時間:3秒, 時間間格:2秒");
        System.out.println("現在時間:" 
            + sdf.format(new Date()));
        
        // schedule(TimerTask task, long 延遲時間, long 時間間格)
        timer.schedule(new DateTask(), 3000, 2000);
       
        try {
            Thread.sleep(10000);
        }
            catch(InterruptedException e) {
        }
        timer.cancel();
        System.out.println("結束時間:" 
            + sdf.format(new Date()) + "\n");
    }
    
    void testScheduleDateAndPeriod(){
        Timer timer = new Timer();
        
        // 設定填入schedule中的 Date firstTime 為現在的15秒後
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND)+15);
        Date firstTime = calendar.getTime();     
       // 也可用 simpleDateFormat 直接設定 firstTime的精確時間
       // SimpleDateFormat dateFormatter = 
        //      new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");  
        // Date firstTime = dateFormatter.parse("2011/12/25 13:30:00");
        
        System.out.println("現在時間:" 
            + sdf.format(new Date()));
        System.out.println("設定執行 Date 為15秒後:" 
            + firstTime +", 時間間格:3秒");
                
        // schedule(TimerTask task, Date 開始時間, long 時間間格)
        timer.schedule(new DateTask(), firstTime, 3000);
                
        try {
            Thread.sleep(30000);
        }
            catch(InterruptedException e) {
        }
        timer.cancel();
        System.out.println("結束時間:" 
            + sdf.format(new Date()) + "\n");
    }
}

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimerTask;
//繼承timertask將要執行的動作覆寫在run裡面
public class DateTask extends TimerTask {
 SimpleDateFormat sdf = new SimpleDateFormat("hh時mm分ss秒 yyyy年MM月dd日");
 private int i=0;
    @ Override
    public void run() {
     i++;
        System.out.println(i+":"+ sdf.format(new Date()));
    }
}

2015年7月21日 星期二

關係(Relation) (三):函數(function)

函數是另一種常見的關係,我們常聽到的函數有二元一次函數跟一元一次函數和三角函數等等

給定兩個nonempty set X,Y,這種relation會有一個特定的對應關係,如同機器一樣經過某種運作方式將X的值轉換成Y,怎麼樣算是一個好的運作方式呢?首先,當然要每一個要方入機器的元素都成產生東西出來,所以對x ∈ X,皆存在y ∈ Y使得(x.y)∈ f,另外我們也希望相同的原料用同一個機器能夠產出固定的產品,所以對所有x ∈ X只會有維一的y ∈ Y使得(x.y)∈f,因此function的定義如下

Definition:
設X,Y為nonempty set 且 f ⊆ X ×Y, 為一個from X to Y的relation.若f滿足下列性質,則稱f為一個from X to Y的函數(function)
(1)對所有x ∈ X, 皆存在 y ∈ Y使得 (x, y) ∈ f .
(2)對所有x ∈ X, 若 y,z ∈ Y 滿足 (x, y) ∈ f 且 (x, z) ∈ f 則,y=z.


一般來說我們很少會用relation來表示function,我們通常會用f : X → Y來表示f是一個從X到Y的function,而對於x ∈ X,我們會使用f(x)=y來表示(x,y) ∈ f

在函數中有一個特別而且簡單的函數叫identity fuction
若f⊆ X ×X為一個from X to X的函數,且對所有x ∈ X,f(x)=x
則f為一個X上的 identity fuction

2015年7月17日 星期五

[Java]static關鍵字


Static這個關鍵字有些人理解是維一的意思,其實他指的是這個屬性是放在類別(class)那一層,不隨著物件(object)的變更去改動的,非static的屬性,每一個物件會有一個值
所以物件A的值改變了,物件B的值並不會改變,但是static的屬性你不管使用物件A、物件B去更動他的值,他的值就是固定在類別上,所以會一起更動,所以他有另一個特性:可以用類別名稱去呼叫,最簡單的例子就像是Math.pow()這種方法(method)一樣,他是static的,如果這個方法還是自己類別的static方法,甚至可以省略類別名稱直接打上方法,以下是程式範例






public class StaticDemo {

public static void main(String[] args) {
StaticDemo obj1 = new StaticDemo();
StaticDemo obj2 = new StaticDemo();
System.out.println("method1:");
System.out.println(obj1.method1());//1
System.out.println(obj2.method1());//1

System.out.println(obj1.method1());//2
System.out.println(obj2.method1());//2

System.out.println("method2:");
System.out.println(StaticDemo.method2());//1
System.out.println(method2());//2
System.out.println(obj1.method2());//3
System.out.println(obj2.method2());//4

}

private int i1=0;
public int method1(){
i1++;
return i1;
}

private static int i2=0;
//private int i2=0;  //this will compile error
public static int method2(){
i2++;
return i2;
}
}

特別注意的是static的方法裡,要使用這個class的屬性的話,那個屬性就必須是static
不然你就要在裡面new一個自己類別的物件出來使用這個屬性,像是public static void main裡面那樣

2015年7月10日 星期五

[Java]台灣身份證字號產生器

關於驗證身份證字號的方法請參考 身份證字號驗證
這個產生器的原理是隨機產生身份證字號,最後用身份證字號公式計算出最後一碼的數字為多少,再將整個字串拼起來

public class ID {

 

 public static void main(String[] args) {

  

  String idNumber = ID.IDRandom();

  System.out.println("-------IDGeneratorTest-------");

  System.out.println(idNumber);

  System.out.println("-------IDGeneratorTest-------");





 }

 

 

 public String str="";



 public static String IDRandom(){

  



  char[] idByChar = new char[9];

  

  String iDString = "";

     

   //隨機生成A~Z

   int x = (int)Math.floor(Math.random()*26+65);

   idByChar[0] = (char) x;

   

   //隨機生成1~2

   idByChar[1] = (char)(int)Math.floor(Math.random()*2+49);

   

   //隨機產出第3~第9個數字

   for (int i=2;i<9;i++){

    idByChar[i] = (char)(int)Math.floor(Math.random()*10+48);

   }   

   

   //第十個數字由前九個字組成

   

   iDString = new String(idByChar);

   ID id = new ID(iDString);

   int[] temp = new int[10];

   temp[0]= id.D0();

   

   for(int i=1;i<9;i++){

    temp[i]=id.DNumber(i); 

   }

   //最後將字組起來送出

   temp[9]=(10-(id.CheckCode(temp)%10))%10;

   iDString = iDString+temp[9];



   

  return iDString;

 }

 

 //D0是找第一個字的代碼,因為有些數字不規律所以要用很多if做判斷

 private int D0(){

  int D00=0;

  int temp = this.str.codePointAt(0);

  

  if(72>=temp && temp>=65)

  {

   D00 = temp-55;

  }else if(78>=temp&&temp>=74){ 

   D00 = temp-56;

  }else if(86>=temp&&temp>=80){

   D00 = temp-57;

  }else if(90>=temp&&temp>=88)

  {

   D00 =temp-58;

  }

  switch(temp){

  case 74 :

   D00 =temp-39;

  

  case 79 :

   D00 =temp-44;

   break;

  

  case 87 :

   D00 =temp-55;

   break;

  default:

   break;

  }

  

  //這邊是用來檢查使用者輸入小寫時的判斷式

  if(104>=temp && temp>=97)

  {

   D00 = temp-87;

  }else if(110>=temp&&temp>=106){ 

   D00 = temp-88;

  }else if(118>=temp&&temp>=112){

   D00 = temp-89;

  }else if(122>=temp&&temp>=120)

  {

   D00 =temp-90;

  }

  switch(temp){

  case 106 :

   D00 =temp-71;

  

  case 111 :

   D00 =temp-76;

   break;

  

  case 119 :

   D00 =temp-87;

   break;

  default:

   break;

  }   

  return D00;

 }



 

 //DNumber用來撿查第2~第10個字,所以判斷式簡單許多

 private int DNumber(int i){

  int D1=100;

  //這個初始100只是用來表示如果他不是0~9這個值就顯示100

  //也可以用其他數值來表示,但是要避免使用0~9

  int temp = this.str.codePointAt(i);

  if(57>=temp&&temp>=48){

   D1=temp-48;

  }

  return D1;

 }

 

  

 //這邊只是輔助計算身份證是否正確

 private int CheckCode(int[] X){

 

  int x1=Math.floorDiv(X[0],10);

  int x2=X[0]%10;

  

  

  int Y=x1+(9*x2)+(8*X[1]);

   for(int i=2;i<=8;i++)

   {

    Y=(9-i)*X[i]+Y;

   }

  

  return Y;

 }

     

 public void ChangeID(String s){

  this.str=s;

 }

 

 public ID(String s){

  this.str=s;

 }

 public ID(){

  

 }

}

2015年7月9日 星期四

[Java]台灣身份證字號驗證器

關於身份證的規則請查照中華民國國民身份證wiki
codePointAt(i)這個方法是用來取出字串第i位置的字的編碼(左邊數來第一個字位置為0)
ASCII table請參照此ASCII wiki

如果要找的是產生器請看此:身份證字號產生器


public class ID {

 

 public static void main(String[] args) {




  //將要測試的身份證字號填入此
  ID id = new ID("A123456789");
  // --------------------------


  //IDcheack回傳的是true跟false

  if(id.IDCheak()){

   System.out.println("This ID Number is leagal");

  }else {

   System.out.println("This ID Number is illeagal");

  }

  

 }

 

 

 

 public String str="";



 //檢查是否為身份證字號並回傳True或False

 public boolean IDCheak(){

   



  ID id= new ID(this.str);

  int[] D= new int[10];

   

   

  //身份正字號長度必須為10個字

  if(str==null || str.length()!=10)

  {

   return false;

  }

  //首字為英文,然後第二位數為1~2

  if(!(id.D0()!=0&&id.DNumber(1)>0&&id.DNumber(1)<3)){

   return false;

  }      

  //put the first code and the second code

  D[0] =id.D0();

  D[1] =id.DNumber(1);     

  //剩下數值應為0~9

  for(int k=2;k<10;k++){

   if(!(id.DNumber(k)>=0&&id.DNumber(k)<=9))

   {

    return false;

   }

   

   D[k] =id.DNumber(k);

  }

  

   

  int cheakCode =0;

   

  cheakCode=(10-(id.CheckCode(D)%10))%10;

   if(cheakCode!=D[9])

   {

    return false;

   }

   

  return true;

 }

 

 //D0是找第一個字的代碼,因為有些數字不規律所以要用很多if做判斷

 private int D0(){

  int D00=0;

  int temp = this.str.codePointAt(0);




  if(72>=temp && temp>=65)

  {

   D00 = temp-55;

  }else if(78>=temp&&temp>=74){ 

   D00 = temp-56;

  }else if(86>=temp&&temp>=80){

   D00 = temp-57;

  }else if(90>=temp&&temp>=88)

  {

   D00 =temp-58;

  }

  switch(temp){

  case 74 :

   D00 =temp-39;

  

  case 79 :

   D00 =temp-44;

   break;

  

  case 87 :

   D00 =temp-55;

   break;

  default:

   break;

  }

  

  //這邊是用來檢查使用者輸入小寫時的判斷式

  if(104>=temp && temp>=97)

  {

   D00 = temp-87;

  }else if(110>=temp&&temp>=106){ 

   D00 = temp-88;

  }else if(118>=temp&&temp>=112){

   D00 = temp-89;

  }else if(122>=temp&&temp>=120)

  {

   D00 =temp-90;

  }

  switch(temp){

  case 106 :

   D00 =temp-71;

  

  case 111 :

   D00 =temp-76;

   break;

  

  case 119 :

   D00 =temp-87;

   break;

  default:

   break;

  }   

  return D00;

 }



 

 //DNumber用來撿查第2~第10個字,所以判斷式簡單許多

 private int DNumber(int i){

  int D1=100;

  //這個初始100只是用來表示如果他不是0~9這個值就顯示100

  //也可以用其他數值來表示,但是要避免使用0~9

  int temp = this.str.codePointAt(i);

  //use variable to determine the code of the i-th character of the string

  if(57>=temp&&temp>=48){

   D1=temp-48;

  }

  return D1;

 }

 

 

 

 

 

 //這邊只是輔助計算身份證是否正確

 private int CheckCode(int[] X){

 

  int x1=Math.floorDiv(X[0],10);

  int x2=X[0]%10;

  

  

  int Y=x1+(9*x2)+(8*X[1]);

   for(int i=2;i<=8;i++)

   {

    Y=(9-i)*X[i]+Y;

   }

  

  return Y;

 }

     

 public void ChangeID(String s){

  this.str=s;

 }

 

 public ID(String s){

  this.str=s;

 }

 public ID(){

  

 }

}

2015年7月7日 星期二

[Java]整數轉字串/字元,字串/字元轉整數(int to String/char and String/cha to int)

在Java中,如果要將數字轉換成字元或字串,或是反過來將字元字串轉成數字的時候,要充份了解互相轉換的機制,比如說
(char)49會將49以編碼的方式轉換,於是顯示出來的數字是1

如果想要將數字轉換成對應的字元,我通常會先轉換成字串再轉成字元
或許有更好的方法,以下列出各種字元/字串對應成整數的方法


public class demo {



 public static void main(String[] args) {



  int i = 1;

  System.out.println("int to String");//整數轉換成字串

  System.out.println(Integer.toString(i));//1 String

  System.out.println(""+i);//1 String

  System.out.println("int to char");

  System.out.println("");



  int i2 = 49;

                //整數強制型別轉換成字元會當成編碼解讀

  System.out.println((char)i2);//1 char

                //轉換成字串在拆成字元

  System.out.println((""+i2).charAt(0));//4 char

  System.out.println((""+i2).charAt(1));//9 char

  System.out.println("");



  char ch = '1';

  System.out.println("char to int");

                //強制型別轉換會將字元轉換成編碼數字

  System.out.println((int)ch);//49 int

                //Character.getNumbericValue()才能取到原來數字

  System.out.println(Character.getNumericValue(ch));//1 int

  System.out.println("");

  

  String str ="1";

  System.out.println("String to int");

                //Inter.parseInt()可將字串轉為數字

  System.out.println(Integer.parseInt(str));//1 int

                //需要讀取字串的編碼數字需要用codePointAt()

  System.out.println(str.codePointAt(0));//49 int, ascii of 1

  System.out.println("");

 }



}

2015年7月5日 星期日

[Javascript]驗證表單及停用按紐的方式

昨天聽到朋友說表單有個disable的功能
javascript可以使用.disabled=false和.disabled=true來開關按紐或是輸入表格的地方
於是我試著實作出驗證的表單
結果網頁在此

範例輸入
姓名:張三
密碼:a123@A
日期:2015/07/05


<!DOCTYPE html>



<html>

 <head lang="zh-tw">

  <meta charset="UTF-8">

  <title>驗證表單</title>

         <style>



   fieldset{

                margin: 0px auto;

    width:625px;

    border-radius: 15px;

    border-color:#00FFFF;

   }

   .title{

    width:450px;

    border-bottom:1px solid #000000;

    border:3px;

    padding:0;

   }

   .t {

    width:100px;

    margin: 10px;

    text-align: right;

    vertical-align:auto;

   }

  </style>

        <script>

            window.onload = function () {

                document.getElementById("nm").onblur = checkName;

                document.getElementById("pw").onblur = cheackPassword;

                document.getElementById("dt").onblur = checkDate;

    document.getElementById("clean").onclick = cleanForm;

            }



        </script>



 </head>



 <body>

  <header>

   

   </div>

  </header>

  <article>

            <h2 style="text-align:center;color:#FF0000">驗證表單</h2>

            <br>

          

            <form action="#" method="post" id="demoform">

                <fieldset>

    <legend>Form Check</legend>

                    <div class="title">

                    <label class="t">姓名:</label><input type="text" id="nm">

                        <span id="nmr"></span><br>

                        <label class="t">不可空白,至少兩個字且必須中文字</label>

                    </div><br>

                   

                   

                  

                    <div class="title">

                    <label class="t">密碼:</label><input type="text" id="pw">

                        <span id="pwr"></span><br>

                        <label class="t">密碼不為空,至少六個字,不為中文,必須</label><br>

                        <label class="t">包含英文、數字、特殊字元(!@#$%^&*)</label>

                    </div><br>

                    <div class="title">

                    <label class="t">日期:</label><input type="text" id="dt">                       

                        <span id="dtr"></span><br>

                        <label class="t">格式:西元年/月/日(ex:2000/02/29)</label>

                    </div><br>      

                     

                    <div class="title">              

           <label class="t"> </label>

           <input type="button" id="goOut"  disabled="disabled" value="送出">

           <input type="reset" id="clean" value="清除">

                    </div><br>

                </fieldset>

            </form>   

  </article>

  <script>

   var nameValue

   var passwordValue

   var dateValue



   function buttonDisable(){

    if(nameValue&&passwordValue&&dateValue){

     document.getElementById('goOut').disabled=false;

    }else{

     document.getElementById('goOut').disabled=true;

    }

   }



   function cleanForm(){

    nameValue = false;

    passwordValue = false;

    dateValue = false;

    document.getElementById("nmr").innerHTML ="";

    document.getElementById("pwr").innerHTML="";

     document.getElementById("dtr").innerHTML ="";

    buttonDisable();

   }



   function checkName() {

    var thePassword = document.getElementById("nm").value;

    var re = /^[\u4e00-\u9fa5]{2,}$/;

    if (thePassword.length >= 2) {

     if (re.test(thePassword)) {

      nameValue = true;

      document.getElementById("nmr").innerHTML = "輸入正確";

     } else {

      nameValue = false;

      document.getElementById("nmr").innerHTML = "格式有誤";

     }



    } else {

     nameValue = false;

     document.getElementById("nmr").innerHTML = "姓名至少兩個字";

    }

    buttonDisable();

   }





   function cheackPassword() {

    var thePassword = document.getElementById("pw").value;

    var re = /^(?=.*[0-9])(?=.*[A-Za-z])(?=.*[!@#\$%\^&\*])(?!.*[\u4e00-\u9fa5])(?!.*[\s]).{6,}$/;

    if (thePassword.length >= 6) {

     if (re.test(thePassword)) {

      passwordValue = true;

      document.getElementById("pwr").innerHTML="輸入正確";

     } else {

      passwordValue = false;

      document.getElementById("pwr").innerHTML="密碼格式有誤";

     }



    } else {

     passwordValue = false;

     document.getElementById("pwr").innerHTML="至少六個字";

    }

    buttonDisable();



   }

   function checkDate() {

    var theDate = document.getElementById("dt").value;

    var re = /^\d{4}[\/]{1}\d{1,2}[\/]{1}\d{1,2}$/;

    var thisDate = new Date(theDate);

    var thisDay = thisDate.getDate();

    

    if (re.test(theDate)) {

     var theDateSubDay = theDate.split("/");

     if (theDateSubDay[2] == thisDay) {

      dateValue = true;

      document.getElementById("dtr").innerHTML = "輸入正確";

     } else {

      dateValue = false;

      document.getElementById("dtr").innerHTML = "日期格式有誤";

     }



    } else {

     dateValue = false;

     document.getElementById("dtr").innerHTML = "輸入格式應為yyyy/MM/dd";

    }

    buttonDisable();



   }

 </script>

 </body>

</html>

2015年7月3日 星期五

關係(Relation) (二):Order(排序)

Relation中還有一種特別的關係,叫做Order relation,所謂的排序關係符合一些特別的性質,以下是介紹。

假設 X 為 nonempty set 且≼ 為 X 上的 relation. 若X符合以下三種性質,我們稱≼為X上的partial order

1.對所有的x ∈ X,皆有 x ≼ x
2.若x,y ∈ X,x≼y且y≼ x,則 x=y
3.若x,y,z ∈ X ,x≼y且y≼z,則 x≼z

跟據上一篇等價關係的敘述我們知道這個關係有ReflexiveTransitive兩種性質,不過第二點這個性質並不是Symmetric,我們稱這種性質為Anti-symmetric,像是大於等於跟小於等於這兩種關係都有這種性質。

假設X 為  nonempty set 且≺為 X上的 relation.若 ≺ 符合以下兩種性質,我們稱 ≺為 X上的 strict total order. 

1.若x,y,z ∈ X 滿足x≺y且y≺z,則 x≺z
2.對所有x,y∈ X,皆會滿足x≺y,y≺x,x=y的其中之一,並且只會剛好滿足其中之一。


partial order跟strict total order在排序上的差別就是有沒有關係排序的時候所有元素都要有關係comparable,像是在銀行領錢的時候有兩三列在排隊,那是一種partial order,你前面會有站人,你也會排在別人前面,可是你左右兩排的人既不是排在你前面,也不是排在你後面。

另外舉個partial order的例子,1~100的整數,若是最左邊的數字相同,則比較實際數值大小
最最我邊位數不同,則兩數沒有排序關係。
例:15 ≼15,15 ≼100,2 ≼23,23 ≼24,但是35跟45就沒有關係。

strict total order是整個集合裡面要完整個排出順序來,所以任意兩個元素互相比較一定有前面跟後面的關係,整數從小排到大或從大排到小就是一個常見的排序關係。

排序會因為排序的方法不同造成同一個集合的關係不一樣,像是A-Z跟a-z這些英文字母,
如果是先比大小寫,再比字母順序的話,排序方式為:A,B,C,D...,Z,a,b...,z
但是如果先比字母順序,再比大小寫的話,排序方式為:A,a,B,b,C,c...,Z,z

最後,排序跟能不能比大小不同,你只要訂好一個規則,那些規則滿足排序的性質,就算是一個排序,而比大小要去檢查他們任兩個元素能不能有>或<的關係,所以以後聽到某個集合不能比大小時,不要直覺就認為這個集合不能排序

[Java]日期格式化-SimpleDateFormat

在Java裡面時間轉換格式是一個很麻煩的課題

因為時間的表達方法各種各樣,有些人寫2015/07/03,有些人寫07/03/2015,有些人寫July 03 /2015,麻煩的是07/03到底表示的是三月七號還是七月三號呢?
所以在Java裡面有個class來格式化日期的類別叫SimpleDateFormat
關於格式的設定詳情請看api文件Date and Time Patterns
格式設定的語法大概如下
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
注意大寫的M代表月份,小寫的m代表的是分鐘

主要的方法有兩個:parse跟format
parse是把字串轉換成日期型態
format是將日期型態轉換成字串

最後特別提一個setLenient方法,他會另外檢查你輸入的值合不合法
預設值是true,改為false的話你輸入15月他會跳出錯誤訊息,如果是true輸入15月或是40日這種他會自動轉成第二年三月或是第二個月10日等等。

以下是範例程式碼

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;





public class DateFormatDemo {



 public static void main(String[] args) throws ParseException {



  SimpleDateFormat sdfor = new SimpleDateFormat("yyyy/MM/dd");

  Date date = sdfor.parse("2015/07/03");

  System.out.println(date);//Fri Jul 03 00:00:00 CST 2015

  System.out.println(sdfor.format(date));//2015/07/03

  

  sdfor = new SimpleDateFormat("yyyy/mm/dd");

  date = sdfor.parse("2015/07/03");

  System.out.println(date);//Sat Jan 03 00:07:00 CST 2015

  

  sdfor = new SimpleDateFormat("yyyy");

  date = sdfor.parse("2015");

  System.out.println(date);//Thu Jan 01 00:00:00 CST 2015

  System.out.println(sdfor.format(date));//2015

  

  sdfor = new SimpleDateFormat("MM月");

  date = sdfor.parse("12月");

  System.out.println(date);//Tue Dec 01 00:00:00 CST 1970

  System.out.println(sdfor.format(date));//12月

  

  

  SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");  

  System.out.println(sdf.parse("1985/15/48"));

  

//  sdf.setLenient(false);

//  System.out.println(sdf.parse("1985/15/48"));//執行會跳exception

 }



}//end of class