2023年10月20日 星期五

變異數和標準差

> 旅遊時,導遊說我們的團平均年齡是30歲,但一去時,發現大部分都是爺爺奶奶帶孫子去玩,確時是平均30沒錯,但有可能會以為大部分都 30 左右,所以這時就有標準差的出現,0 表示都是30,數字越大就差越多

假設有一筆資料

1 3 3 9

1. 求平均數: 加總是 16,平均是 16 / 4 = 4


2. 每筆資料減去平均數並平方

(1 - 4) 平方 = 9

(3 - 4) 平方 = 1

(3 - 4) 平方 = 1

(9 - 4) 平方 = 25


3. 將結果加起來除平均數

9 + 1 + 1 + 25 = 36

36 / 4 = 9

此時會得到變異數


4. 求標準差

變異數的根號就是標準差,所以根號 9 等於 3 為標準差



依照上面的公式,假設總數都 16

4 4 4 4

(4 - 4) 平方都是 0

變異數為 0 / 4 = 0

根號 0 還是 0

所以看到 0 表示很平均的


又假設是

13 1 1 1

(13 - 4) 平方 = 81

(1 - 1) 平方都是 0

變異數為 81 / 4 = 20.25

根號 20.25 約是 4.多


最後是 16 0 0 0

變異數是 36,根號後為 6,所以正數時,最多就是 0~6 了

windows 標準輸出

 # 標準輸出

> 正確的命令 > 檔案,也可用 1>

> 正確的命令表示打完後「不會」出錯

1. echo xxx > d:\abc.txt

2. echo xxx 1> d:\abc.txt

每次都會清空之前的內容

---


 # 標準附加輸出

> 正確的命令 >> 檔案,也可用 1>>

1. echo xxx >> d:\abc.txt

2. echo xxx 1>> d:\abc.txt

每次都「不會」清空之前的內容,會在檔案最後附加上去

---


 # 標準錯誤輸出、標準錯誤附加輸出

> 不正確的命令 2> 檔案

> 不正確的命令表示打完後會出錯

xxx > d:\abc.txt

每次都會清空之前的內容

如果要附加,只要將 2> 改成 2>> 即可

---


 # 標準輸出、標準錯誤輸出導出不同檔案

1. echo xxx >> d:\abc.txt 2>> aaa.txt

2. echo xxx > d:\abc.txt 2> aaa.txt

不可以導到相同的檔案,>,2>>都和上面說的一樣,可以自己決定要不要附加

---


# 標準輸出、標準錯誤輸出導出相同檔案

1. echo xxx >> d:\abc.txt 2>&1

2. xxx >> d:\abc.txt 2>&1

只要在最後加上 2>&1 即可,附加看的是前面的標準輸出或標準附加輸出


2023年1月26日 星期四

java Native 調用 C

public class TestNative {
    public native void helloNative1();
    public static native void helloNative2();

    static {
        System.load(System.getProperty("user.dir") + "/xxx.dll");
    }

    public static void main(String[] args) {
        new TestNative().helloNative1();
        TestNative.helloNative2();
    }
}

※System.getProperty("user.dir") 為專案路徑
※xxx.dll 為 c 的程式碼變成的


產生 dll 的方法:
1.到 TestNative.java 打上 javac TestNative.java -h .
會產生副檔名為 h 和 class 的檔案

2.將副檔名為 h 的檔案複製一份出來改檔名為 cpp,完成後為如下的圖:


3.修改 cpp 檔案的內容,這個就是要實作 native 的內容

#include <jni.h>
#include <stdio.h>
#include "TestNative.h"

JNIEXPORT void JNICALL Java_TestNative_helloNative1
  (JNIEnv *, jobject) {
  printf("%s", "helloNative1\n");
  }

JNIEXPORT void JNICALL Java_TestNative_helloNative2
  (JNIEnv *, jclass) {
  printf("%s", "helloNative2\n");
  }

※要 include TestNative.h

4.到 sourceforge.net 下載 c 的編譯器 MinGW-w64,然後如下下載,並解壓



5.進入解壓後的資料夾的 bin
打上 gcc --version,出現版本號表示可以用 gcc 這個指令了
再打上 gcc -I "C:\Program Files\Java\jdk1.8.0_202\include" -I "C:\Program Files\Java\jdk1.8.0_202\include\win32" --shared -o xxx.dll D:\JavaProject\src\TestNative.cpp
會產生 xxx.dll 的檔案

※-I 表示 include,要包含兩個檔案,因為 3 的檔案要用到 jni.h,這個檔案在 include 裡;然後 jni.h 這個檔案還要 include jni_md.h,這個檔案在 include\win32

※-o 為 output,後面接想輸出的檔案名稱

※最後是 cpp 所在路徑

6.將得到的 xxx.dll 放在專案路徑下即可,其他 cpp、h 都可以不需要,結果畫面如下:










2023年1月9日 星期一

C語言指針

 線上測試

※基本型態指針

// 包括 short int long float double chat

#include <stdio.h>

void test(int *d)  {

    *d = 100; // 將 d 這個位址對應的值,改成 100; 寫 d 或 &d 都會報錯

}


int main() {

    int digit = 2;

    test(&digit);

    printf("digit=%d", digit);

    return 0;

}


在變數前加上 &,表示傳的是記憶體位址;

    在變數前加上 *,表示接收記憶體位址

    所以可以這樣宣告變數 int *x = &digit;   test(x);

※這樣的好處是方法裡改變的值,會影響調用方的值

※只有傳的時候給 &,接收時給 * 才不會報錯,其他都會報錯



※陣列指針

#include <stdio.h>


int main() {

    int arr[] = {1, 2, 3};


    // 注意是用 int *p 來接,不是 int[]*p,會報錯

    int *p = arr; // 指向的是 arr[0]的記憶體位址,陣列不可打 &arr,因為它有多個值,要傳其中一個值可用 &arr[0],但代表整體就不能有 &,會報錯

    

    // 以下三個結果一樣

    printf("%p\n", &arr[0]);

    printf("%p\n", arr);

    printf("%p\n", p);

    

    // 以下三個結果一樣,和上面差 4,也就是 4 Bytes

    printf("%p\n", &arr[1]);

    printf("%p\n", arr + 1);

    printf("%p\n", p + 1);

    

    // 以下三個結果都是 2,也就是取值

    printf("%d\n", *(&arr[1]));

    printf("%d\n", *(arr + 1));

    printf("%d\n", *(p + 1));

    

    printf("%p\n", &arr + 1); // &arr 是整個 arr 的記憶體位址,如果佔用 4Bytes,結果將是 4Bytes 結束再 + 1,可用 sizeof() 查看佔多少 Byte

    return 0;

}



※字串指針

int main() {

    char *p = "a";

    printf("string=%s", p);

    

    // int *i = 9;

    // printf("digit=%d", i);

    return 0;

}

※字串指針可以直接賦值,其他不行


※陣列裡放指針

int main() {

    char *s1 = "ab";

    char *s2 = "cd";

    char *s3 = "ef";

    

    char *s[3] = {s1, s2, s3}; // 和陣列就差一個 *,只有字串可以這樣寫

    printf("string=%p\n", s);

    printf("%s", s[1]);


    return 0;

}





2022年8月11日 星期四

lambda 的 this (java8 八)

/**
 * 印 this 的時候,會調用 Object.toString()
 * 匿名類別的 this:會先調用自己匿名類別的 toString,沒有才去 Object.toString
 * Lambda 的 this:會先調用「當下」類別的 toString,沒有才去 Object.toString
 */
public class ThisTest {
    Animal a1 = new Animal() {
        @Override
        public void m(String str) {
            System.out.println(this);
        }

//        @Override
//        public String toString() {
//            return "anonymous toString";
//        }
    };

    Animal a2 = s -> System.out.println(this);

//    @Override
//    public String toString() {
//        return "this toString";
//    }

    public static void main(String[] args) {
        ThisTest thisTest = new ThisTest();
        thisTest.a1.m("xxx");
        thisTest.a1.m("aaa");
        thisTest.a2.m("ooo");
        thisTest.a2.m("bbb");
    }

    @FunctionalInterface
    public interface Animal {
        void m(String str);
    }
}


2022年7月14日 星期四

Java 的 floorMod 和 %

// System.out.println(Math.floorMod(113, 30)); // 23
System.out.println(Math.floorMod(113, -30)); // -7
System.out.println(Math.floorMod(-113, 30)); // 7
System.out.println(Math.floorMod(-113, -30)); // -23
System.out.println("-----------------------");
// System.out.println(113 % 30); // 23
System.out.println(113 % -30); // 23
System.out.println(-113 % 30); // -23
System.out.println(-113 % -30); // -23
System.out.println("=======================");
// System.out.println(Math.floorDiv(113, 30)); // 3
System.out.println(Math.floorDiv(113, -30)); // -4
System.out.println(Math.floorDiv(-113, 30)); // -4
System.out.println(Math.floorDiv(-113, -30)); // 3
System.out.println("-----------------------");
// System.out.println(113 / 30); // 3
System.out.println(113 / -30); // -3
System.out.println(-113 / 30); // -3
System.out.println(-113 / -30); // 3

除數和被除數全正數和全負數時,% 和 mod 一模一樣

※全負數時,除法是負負得正;

※有負數時, % 的正負號看左邊,mod 的正負號看右邊,如 -113 % -30,-113 是左邊;-30 是右邊,一正一負時也是一樣

※113 / 30 是 3...23

floorDiv 時,一正一負為負,(3 + 1) * -1 = -4,固定加1乘-1

floorMod 時,30 - 23 = 7,然後看 30 是正或負,7 的正負號就和它一樣

目前不知道 mod 這樣有什麼用