2013/3/31

【C語言】亂數

  閒來無事突然好奇random()函數是不是真的能產生很均勻的數值來,就寫了個小程式將產生的亂數值做餘數處理分配到四個變數,在將最後結果印出來,結果竟然十分均勻,直接先看程式內容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char **argv) {
 int value[4] = {0, 0, 0, 0};
 int max = INT_MAX;

 srand(time(NULL));
 for(int i = 0; i < max; i++) {
  value[rand() % 4] += 1;
 }

 for(int i = 0; i < 4; i++) {
  printf("%d => %d\n", i, value[i]);
 }

 printf("Total: %d\n", max);
 return  0;
}

執行幾次結果大致相同
1
2
3
4
5
0 => 536870911
1 => 536870912
2 => 536870912
3 => 536870912
Total: 2147483647

母體設小一點就比較不那麼均勻

1
2
3
4
5
0 => 14
1 => 10
2 => 9
3 => 17
Total: 50

  說實話這樣的結果其實讓我有點懷疑亂數太過造假,也就是說顯得不自然,雖然這樣的結果符合機率告訴我們的只要母體夠大在公平的條件下大家機會是相等的,不過軟體產生的亂數本來就是依據演算公式不斷疊代產生,因此對於這樣的結果好像也就不需要太意外了!

PS. 環境說明

  • 編譯器:Visual Studio Express 2012 for Windows Desktop
  • 執行環境:Windows 7 SP1

2013/04/02 補充
  同樣程式碼放在Linux下跑,得出來的亂數值有比較符合原先預期的結果,先看執行結果:
第一次執行
1
2
3
4
5
0 => 536849545
1 => 536888948
2 => 536882094
3 => 536863060
Total: 2147483647
第二次執行
1
2
3
4
5
0 => 536877294
1 => 536896031
2 => 536864732
3 => 536845590
Total: 2147483647
不曉得linux下的library在實作此亂數函數時是否也有把一些硬體外在環境因素也加入演算,像是/dev/random與/dev/urandom有把硬體訊號元的變因加入亂數產生演算因子,所以才會得到比較貼近實際的結果?

2012/11/11

【上海】人民公園裡的婚姻角、相親角

在上海人民公園的北面入口處(地鐵九號出口)早上開始會聚集許多人潮來這找尋兒孫的另一伴,沒有寫錯!是替自家兒女或小孫子找尋成家的對象,但我想應該也是會有年輕人自己來這物色對象才是。

這裡的景況應該就像台灣的相親吧!?只是這裡的待選名單都用A4紙張陳列自己的基本資料以及配對條件,等待有緣人來相認...。候選名單都會依據資料特性做分類,在國外工作的一區、碩士學歷的一區、大學學歷的一區、離過婚的一區...。

公園裡還有許多「仲介人員」幫忙做資料登錄與配對篩選,登記配對價錢五十到一百五不等,應該自身條件(高矮胖瘦、有房無房、有車無車...等)會影響費用吧?

這裡的婚介人員一只皮箱即可開業,讓我想到早年的台灣商人也是一只皮箱就到世界各國去招攬生意...XD。

在旁邊一處「散裝」的候選名單似乎是家長拿著自己兒孫的資料在物色媳婦女婿?

2012/11/6

【治具】Audio Loopback Jack

測試Audio Jack一般我們會使用所謂的Audio Loopback線材做迴錄工具,其實就只是把麥克風源跟聲音源的左右聲道給短路在一起而已。但最近有個案子用這樣的治具卻沒辦法回錄到聲音,後來得知在麥克風源與聲音源之間必須加個1uF(5V以上)的電容才可以,接線示意圖如下:
實際接線拍照:

補充雙聲道+麥克風Audio Jack 的結構圖,從最下方開始往上依序為左聲道源、右聲道源、接地與麥克風源:

2012/11/5

【Linux】Bochs模擬器模擬器

Bochs是一套用來模擬IA32架構的模擬器,可以模擬一台完整的PC:CPU, Memory, Disk...等,更棒的是在Debug模式中可以單步執行並隨時觀察CPU暫存器狀態或是記憶體資訊,對於學習PC底層有滿大的幫助,以下記錄下載Source包裝編譯安裝與執行的步驟。
  1. 到Bochs官網下載Source Code與Disk Image
    目前最新Source Code版本是bochs-20121103.tar.gz
    Disk Image這裡用FreeDos作為範例
  2. 完成下載後先對Source Code解壓縮
    tar zxvf bochs-20121103.tar.gz
  3. 作編譯前的設定:這邊開啟Debug與反組譯功能
    ./configure --enable-debugger --enable-disasm
  4. 編譯與安裝
    make
    sudo make install
  5. 以上步驟完成安裝程序, 接下來把下載好的FreeDos映像檔解壓縮
    tar zxvf freedos-img.tar.gz
  6. 切到解壓縮的目錄裡會看到會看到a.img, b.img, bochsrc, 與c.img這幾個檔案, 用gedit編輯器編輯bochsrc設定檔如下[註]
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    megs: 32
    romimage: file=$BXSHARE/BIOS-bochs-latest
    vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
    vga: extension=vbe
    floppya: 1_44=a.img, status=inserted
    ata0-master: type=disk, path=c.img, cylinders=306, heads=4, spt=17
    boot: floppy
    log: bochsout.txt
    mouse: enabled=0
    cpu: ips=15000000
    vga_update_interval: 150000
    
  7. 接著執行bochs即可, 第一個選擇畫面直接選擇6. Begin simulation即可運行模擬器
  8. 但因為編譯設定時有選擇debug模式, 所以會先trap在一開始, 畫面如下:只要輸入c並按下enter模擬器就會繼續執行
  9. 最後成功進入Dos的畫面截圖如下:
[註] bochs執行時可以用-f參數指定要帶起的模擬器參數設定檔, 若沒指定的話則會在當前目錄下依序找尋以下檔案作為設定檔:
  1. .bochsrc
  2. bochsrc
  3. bochsrc.txt
  4. bochsrc.bxrc (Windows Only)

2012/10/31

【Windows8】取得Auto Rotation狀態

先前同事提了個需求要能用程式判斷當前Auto Rotation狀態,查了一下發現有個GetAutoRotationState()函數可以調用,透過這函數呼叫可以查知目前系統Auto Rotation是否被開啟,直接看程式內容吧!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>

#pragma comment (lib, "User32")

int _tmain(int argc, _TCHAR* argv[])
{
 enum tagAR_STATE state;
 bool blResult = GetAutoRotationState(&state);
 if(blResult)
 {
  if(0 == state)
   printf("Auto Rotation: ON\n");
  else
   printf("Auto Rotation: OFF\n");
 }
 else
  printf("Access rotation status ... fail\n");
 return  0;
}

需要注意的是這函數是Windows8才加入User32.dll的,因此如果拿這程式在Windows7以前版本執行的話會遇到這樣的錯誤:
如果要避免這樣的錯誤,需要用動態載入dll方式進行呼叫。

在Windows8上執行截圖如下:


附註:tagAR_STATE詳細屬性:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public enum tagAR_STATE : uint
{
 AR_ENABLED = 0x0,
 AR_DISABLED = 0x1,
 AR_SUPPRESSED = 0x2,
 AR_REMOTESESSION = 0x4,
 AR_MULTIMON = 0x8,
 AR_NOSENSOR = 0x10,
 AR_NOT_SUPPORTED = 0x20,
 AR_DOCKED = 0x40,
 AR_LAPTOP = 0x80
}

Keyword:Windows API、System Call

2012/10/9

【Windows】Process Explorer

  在Windows系統上一般要查看執行中的處理程序可以開啟Windows工作管理員(可用快截鍵Ctrl + Shift + ESC開啟)來查看,這用來查看系統中哪個處理程序吃掉太多CPU或記憶體資源或是想殺掉某些用不到又吃資源的處理程序很好用,但若要進一步查看程式呼叫了哪些DLL、存取哪些Handle或是動了哪些Registry等詳細訊息就不夠用了!

  要進一步查看Process的相關資訊可以到Sysinternals網站下載Process Explorer,這工具以樹狀關係顯示Process之間的關係,把滑鼠移到某個Process上停著會顯示執行擋完整的路徑名稱,連帶起來的參數資訊都會顯示出來,不同的程序也可用不同顏色顯示(ex. 預設Service會以粉紅色顯示、一般程序則是藍色顯示...等),雙點某個程序則會顯示進一步詳細資訊,像是CPU佔用時間、記憶體資源或是IO資訊等,最厲害的大概就是可以查看Process執行載入了哪些DLL或是開啟了哪些Handle資訊,這些資訊對於開發人員要找問題可是有很大的幫助!


2012/8/29

【C++】縮小命令提示字元視窗

上次寫了如何用C#讓命令提示字元視窗在執行時縮小(參考這篇),今天又有同事提出需求要在另一支用C++完成的工具也要做到一樣效果,有了上次的經驗這次很快就完成了任務需求,一樣用FindWindow與ShowWindow系統函數來達成,只是這次要多調用一個GetConsoleTitle函數來做輔助,直接看Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>
#include <Windows.h>

#pragma comment(lib, "User32.lib")

int main(int argc, char* argv[])
{
 char cTitle[512];
 GetConsoleTitle(cTitle, 512);
 HWND hWnd = FindWindow(NULL, cTitle);
 ShowWindow(hWnd, SW_SHOWMINIMIZED);
 return 0;
}

  1. 先用GetConsoleTitle函數取得執行程式命令提示字元的顯示標題列內容。
  2. 再用取得的視窗標題找出HWND。
  3. 最後用FindWindow函數控制視窗的呈現。
  • ShowWindow第二個函數用來決定視窗要如何呈現:最大、最小...等。詳細請參考MSDN說明頁面。