# HW02 參考答案 ## 2.1 $\sqrt{2}$ ```c= #include <stdio.h> #include <stdint.h> #include <float.h> #include <math.h> int main() { uint16_t n = 0; double result = 1.0; double sq2 = sqrt(2.0); // printf("Precision of double: %d decimal digits\n", DBL_DIG); // printf("%.15lf\n", sq2); printf("Please enter n (16-bits unsigned): "); scanf("%hu", &n); for(int32_t i = 1 ; i <= n ; i++){ printf("n = %hu: %.15lf (%.15lf)\n", i, result, result - sq2); result = 1 + (1/(1+result)); } } ``` ## 2.2 Multiplication v2 ```c= #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main() { int64_t a, b; printf("Please enter the first number: "); scanf("%lld", &a); if (a < 0 || 2147483647 < a) { printf("Wrong input, your input must between 0 ~ 4294967295.\n"); return 0; } printf("Please enter the second number: "); scanf("%lld", &b); if (b < 0 || 2147483647 < b) { printf("Wrong input, your input must between 0 ~ 4294967295.\n"); return 0; } uint64_t c = (uint64_t)a * (uint64_t)b; uint64_t len_a = 0, len_b = 0, len_c = 0; if (a == 0) { len_a = 1; } for (uint64_t i = 1; i <= a; i *= 10) { len_a++; if (i == 10000000000UL) { if (a / i > 1) { len_a++; } break; } } if (b == 0) { len_b = 1; } for (uint64_t i = 1; i <= b; i *= 10) { len_b++; if (i == 10000000000UL) { if (b / i > 1) { len_b++; } break; } } if (c == 0) { len_c = 1; } for (uint64_t i = 1; i <= c; i *= 10) { len_c++; if (i == 10000000000000000000UL) { if (c / i > 1) { len_c++; } break; } } uint64_t max_len = len_a > len_b ? len_a : len_b; max_len = max_len > len_c ? max_len : len_c; // print a printf(" "); for (int i = 0; i < max_len - len_a; i++) { printf(" "); } if (a == 0) { printf("0\n"); } else { uint64_t div_a = 1, tmp_a = a; for (int i = 0; i < len_a - 1; i++) { div_a *= 10; } for (int i = 0; i < len_a; i++) { printf("%lld ", tmp_a / div_a); tmp_a %= div_a; div_a /= 10; } printf("\n"); } // print b printf("*)"); for (int i = 0; i < max_len - len_b; i++) { printf(" "); } if (b == 0) { printf("0\n"); } else { uint64_t div_b = 1, tmp_b = b; for (int i = 0; i < len_b - 1; i++) { div_b *= 10; } for (int i = 0; i < len_b; i++) { printf("%lld ", tmp_b / div_b); tmp_b %= div_b; div_b /= 10; } printf("\n"); } //print line for (int i = 0; i < max_len * 2 + 1; i++) { printf("-"); } printf("\n"); if (len_b != 1 && c != 0) { uint64_t tmp_b = b; for (int i = 0; i < len_b; i++) { uint64_t d = (tmp_b % 10) * a, len_d = 0; if (d == 0) { len_d = 1; } else { for (uint64_t j = 1; j <= d; j *= 10) { len_d++; if (j == 10000000000UL) { if (d / j > 1) { len_d++; } break; } } } // print middle printf(" "); for (int j = 0; j < max_len - len_d - i; j++) { printf(" "); } uint64_t div_d = 1; for (int j = 0; j < len_d - 1; j++) { div_d *= 10; } for (int j = 0; j < len_d; j++) { printf("%lld ", d / div_d); d %= div_d; div_d /= 10; } printf("\n"); tmp_b /= 10; } //print line for (int i = 0; i < max_len * 2 + 1; i++) { printf("-"); } printf("\n"); } // print c printf(" "); for (int i = 0; i < max_len - len_c; i++) { printf(" "); } if (c == 0) { printf("0\n"); } else { uint64_t div_c = 1, tmp_c = c; for (int i = 0; i < len_c - 1; i++) { div_c *= 10; } for (int i = 0; i < len_c; i++) { printf("%lld ", tmp_c / div_c); tmp_c %= div_c; div_c /= 10; } printf("\n"); } return 0; } ``` ## 2.3 Non-deterministic Finite State Machine :::spoiler 簡單的解答 ```c #include <inttypes.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #define ever (;;) // 無窮迴圈的巧妙寫法 int main() { // 定義各狀態變數 bool S0_active = true, S1_active = false, S2_active = false, S3_active = false, S4_active = false, S5_active = false, S6_active = false; // 定義各狀態的下一個狀態變數 bool next_S0_active, next_S1_active, next_S2_active, next_S3_active, next_S4_active, next_S5_active, next_S6_active; int64_t input; // 輸入整數 bool is_even; // 判斷輸入是否為偶數 int8_t remaining; // 紀錄尚有幾個最終狀態未輸出 // 無窮迴圈 for ever { printf("Please enter an integer: "); scanf("%" SCNd64, &input); // 若輸入為 0,則跳出迴圈 if (input == 0) { break; } // 初始化各狀態的下一個狀態為 false next_S0_active = false; next_S1_active = false; next_S2_active = false; next_S3_active = false; next_S4_active = false; next_S5_active = false; next_S6_active = false; is_even = input % 2 == 0; // 判斷輸入是否為偶數 // 根據各狀態當前是否存在和輸入奇偶性,計算下一個狀態 // 下一個狀態存儲在 next_Sx_active 變數中 if (S0_active) { if (is_even) { next_S3_active = true; } else { next_S1_active = true; next_S2_active = true; } } if (S1_active) { if (is_even) { next_S4_active = true; } else { next_S2_active = true; } } if (S2_active) { if (is_even) { next_S5_active = true; } else { next_S3_active = true; } } if (S3_active) { if (is_even) { next_S0_active = true; } else { next_S5_active = true; } } if (S4_active) { if (is_even) { next_S2_active = true; next_S6_active = true; } else { next_S5_active = true; } } if (S5_active) { if (is_even) { next_S0_active = true; } else { next_S6_active = true; } } if (S6_active) { if (is_even) { next_S1_active = true; } else { next_S6_active = true; } } // 更新狀態 S0_active = next_S0_active; S1_active = next_S1_active; S2_active = next_S2_active; S3_active = next_S3_active; S4_active = next_S4_active; S5_active = next_S5_active; S6_active = next_S6_active; } // 計算共有幾個最終狀態 remaining = S0_active + S1_active + S2_active + S3_active + S4_active + S5_active + S6_active; // 輸出所有可能的狀態 printf("Possible States: "); if (S0_active) { printf("S0"); --remaining >= 1 && printf(", "); } if (S1_active) { printf("S1"); --remaining >= 1 && printf(", "); } if (S2_active) { printf("S2"); --remaining >= 1 && printf(", "); } if (S3_active) { printf("S3"); --remaining >= 1 && printf(", "); } if (S4_active) { printf("S4"); --remaining >= 1 && printf(", "); } if (S5_active) { printf("S5"); --remaining >= 1 && printf(", "); } if (S6_active) { printf("S6"); --remaining >= 1 && printf(", "); } printf("\n"); return EXIT_SUCCESS; } ``` ::: :::spoiler 三成就解答(Credit: 41247006S 張O義) ```c #include <stdint.h> #include <stdio.h> uint8_t state = 0b00000001; // 0000 0001, from left to right: non_define, S6 ~ S0 // initial state: S0 uint8_t state_trans(uint8_t); uint64_t odd = 0b01000000010000000010000000100000000010000000010000000110; // S6~S0 0100 0000 /0100 0000 /0010 0000 /0010 0000 /0000 1000 /0000 0100 /0000 0110 uint64_t even = 0b00000010000000010100010000000001001000000001000000001000; // S6~S0 0000 0010 /0000 0001 /0100 0100 /0000 0001 /0010 0000 /0001 0000 /0000 1000 int main() { int64_t n = 1; while (n != 0) { printf("Please enter an integer: "); scanf("%ld", &n); if (n != 0) state = state_trans(n % 2); } printf("Possible States:"); for (uint16_t i = 1, j = 0; j < 7; i <<= 1, j++) { if (state & i) { if (n != 0) printf(","); printf(" S%d ", j); n = 1; } } printf("\n"); // printf("Debug: state = %d\n",state); return 0; } uint8_t state_trans(uint8_t k) { // k = 0: n is even // k = 1: n is odd uint8_t result = 0; if (k) { for (uint8_t i = 1, j = 0; j < 7; i <<= 1, j++) if (state & i) result |= (odd >> j * 8); } else { for (uint8_t i = 1, j = 0; j < 7; i <<= 1, j++) if (state & i) result |= (even >> j * 8); } return result; } ``` ::: :::spoiler 很好理解的成就二解答(Credit: 41009035E 戴O彩) ```c #include <stdint.h> #include <stdio.h> #define CHECK_BIT(var, pos) (((var) >> (pos)) & 1) // check bit: read number is 1 or not uint8_t stateMachineStatus = 0b00000001; // binary uint8_t s0 = 0b00000001; // 0th bit 1 as S0 state uint8_t s1 = 0b00000010; // 1st bit 1 as S1 state uint8_t s2 = 0b00000100; // 2nd bit 1 as S2 state uint8_t s3 = 0b00001000; // 3rd bit 1 as S3 state uint8_t s4 = 0b00010000; // 4th bit 1 as S4 state uint8_t s5 = 0b00100000; // 5th bit 1 as S5 state uint8_t s6 = 0b01000000; // 6th bit 1 as S6 state void MoveToNextState(int num); int main() { int32_t num; while (1) { printf("Please enter an integer: "); scanf("%d", &num); if (num == 0) { int count = 0; printf("Possible States: "); for (int i = 0; i < 7; i++) { if (CHECK_BIT(stateMachineStatus, i)) { if (count > 0) { printf(", S%d", i); } else { printf("S%d", i); } count = count + 1; } } printf("\n"); break; } else { MoveToNextState(num); } } return 0; } void MoveToNextState(int num) { uint8_t stateMachineStatusChange = 0; if (CHECK_BIT(stateMachineStatus, 0)) // S0 { if ((num % 2) == 0) // even Number { stateMachineStatusChange = stateMachineStatusChange | s3; } else // odd number { stateMachineStatusChange = stateMachineStatusChange | s1; stateMachineStatusChange = stateMachineStatusChange | s2; } } if (CHECK_BIT(stateMachineStatus, 1)) // S1 { if ((num % 2) == 0) { stateMachineStatusChange = stateMachineStatusChange | s4; } else { stateMachineStatusChange = stateMachineStatusChange | s2; } } if (CHECK_BIT(stateMachineStatus, 2)) // S2 { if ((num % 2) == 0) { stateMachineStatusChange = stateMachineStatusChange | s5; } else { stateMachineStatusChange = stateMachineStatusChange | s3; } } if (CHECK_BIT(stateMachineStatus, 3)) // S3 { if ((num % 2) == 0) { stateMachineStatusChange = stateMachineStatusChange | s0; } else { stateMachineStatusChange = stateMachineStatusChange | s5; } } if (CHECK_BIT(stateMachineStatus, 4)) // S4 { if ((num % 2) == 0) { stateMachineStatusChange = stateMachineStatusChange | s6; stateMachineStatusChange = stateMachineStatusChange | s2; } else { stateMachineStatusChange = stateMachineStatusChange | s5; } } if (CHECK_BIT(stateMachineStatus, 5)) // S5 { if ((num % 2) == 0) { stateMachineStatusChange = stateMachineStatusChange | s0; } else { stateMachineStatusChange = stateMachineStatusChange | s6; } } if (CHECK_BIT(stateMachineStatus, 6)) // S6 { if ((num % 2) == 0) { stateMachineStatusChange = stateMachineStatusChange | s1; } else { stateMachineStatusChange = stateMachineStatusChange | s6; } } stateMachineStatus = stateMachineStatusChange; } ``` ::: ## 2.4 Dollar Cost Averaging Calculator Credit: 41247004S 廖O翔 ```c #include <stdio.h> #include <stdint.h> int32_t rounded(int32_t rate) { if(rate%10 < 5) return rate/10; else return (rate/10)+1; } int32_t int_judge(double input) { if (input-(int32_t)(input) > 0) return 1; else return 0; } int main(int argc, char const *argv[]) { double i_investment = 0, monthly_investment = -1, s_month = 0, s_year = 0, e_month = 0, e_year = 0; double initial_investment = 0, y_rate = 0, m_rate = 0; printf("Initial Investment:\t\t"); scanf("%lf", &i_investment); if (int_judge(i_investment)) { printf("Error: please enter a integer.\n"); return 11; } if (i_investment < 1 || i_investment > 10000000) { printf("Error: please enter a integer for Initial Investment between 1~10000000\n"); return 1; } initial_investment = i_investment; printf("Recurring Monthly Investment:\t"); scanf("%lf", &monthly_investment); if (int_judge(monthly_investment)) { printf("Error: please enter a integer.\n"); return 11; } if (monthly_investment < 0 || monthly_investment > 10000000) { printf("Error: please enter enter a integer for Recurring Monthly Investment between 0~10000000\n"); return 1; } printf("Start Month:\t\t\t"); scanf("%lf", &s_month); if (int_judge(s_month)) { printf("Error: please enter a integer.\n"); return 11; } if (s_month < 1 || s_month > 12) { printf("Error: please enter enter a integer for Start Month between 1~12\n"); return 1; } printf("Start Year:\t\t\t"); scanf("%lf", &s_year); if (int_judge(s_year)) { printf("Error: please enter a integer.\n"); return 11; } if (s_year < 1 || s_year > 10000) { printf("Error: please enter enter a integer for Start Year between 1~10000\n"); return 1; } printf("End Month:\t\t\t"); scanf("%lf", &e_month); if (int_judge(e_month)) { printf("Error: please enter a integer.\n"); return 11; } if (e_month < 1 || e_month > 12) { printf("Error: please enter enter a integer for End Month between 1~12\n"); return 1; } printf("End Year:\t\t\t"); scanf("%lf", &e_year); if (int_judge(e_year)) { printf("Error: please enter a integer.\n"); return 11; } if (e_year < 1 || e_year > 10000) { printf("Error: please enter enter a integer for End Year between 1~10000\n"); return 1; } printf("Annual Rate of Return (%%):\t"); scanf("%lf", &y_rate); if (int_judge(y_rate)) { printf("Error: please enter a integer.\n"); return 11; } if (y_rate < 1 || y_rate > 100) { printf("Error: please enter enter a integer for Annual Rate of Return between 1~10000000\n"); return 1; } if (e_year-s_year < 0 || (e_year-s_year == 0 && e_month-s_month <= 0) ) { printf("Error: Time range must larger than a month.\n"); return 1; } m_rate = (y_rate/12)/100; // printf("%lf\n", m_rate); printf("--- Output ---\n"); double total = initial_investment, investment = initial_investment; int32_t month = s_month; for (int32_t year = s_year; year <= e_year; year++) { for (; month <= 12; month++) { int32_t rate = (int32_t)(((total-initial_investment)/total)*100000); rate = rounded(rate); printf("%d.", year); if (month < 10) printf("0"); if (initial_investment < 1000000000000000 && total < 1000000000000000) if (rate%10 > 0 ) printf("%d) %.0lf/%.0lf/%.0lf/%.2lf%%\n", month, initial_investment, total, total-initial_investment, rate/100.0); else if (rate % 100 > 0) printf("%d) %.0lf/%.0lf/%.0lf/%.0lf.%.0lf%%\n", month, initial_investment, total, total-initial_investment, (double)(rate/100), (double)(rate%100)/10); else printf("%d) %.0lf/%.0lf/%.0lf/%.0lf%%\n", month, initial_investment, total, total-initial_investment, (double)(rate/100)); else printf("%d) */*/*/*%%\n", month); if (year == e_year && month == e_month-1) { break; } investment = total*(1+m_rate); total = investment + monthly_investment; initial_investment += monthly_investment; } month = 1; } return 0; } ``` ## 2.5 Catan Simple Islands Engine ```c= #include <stdio.h> #include <stdint.h> #include <stdbool.h> int main(){ int32_t L = 0; int32_t N = 0; printf("Please input the length: "); scanf("%d", &L); printf("Please input the number of layer: "); scanf("%d", &N); uint64_t max_width = (2*N-1)*(2*L-2)+L; if(max_width > 80){ printf("Error\n"); return 0; } // upper for(int32_t outi = 1; outi <= 2*N-1; outi ++){ int32_t outj = outi; for(int32_t inni = 0; inni < L-1; inni ++){ int32_t base = 1+(N-outi)*(2*L-2); for(int32_t j = 0; j < base; j ++){ printf(" "); } for(int32_t innj = base; innj < base+outj*(4*L-4); innj ++){ if(innj < 0 || innj >= max_width){ continue; } int32_t basej = (innj - base)%(4*L-4); int32_t basei = inni; bool left_slope = basei+basej==(L-2), mid_line = (basei==0 && basej >= L-2 && basej <= L-2+L-1 ), right_slope = basej-basei==2*L-3; if(left_slope + mid_line + right_slope >= 2){ printf("*"); }else if(left_slope){ printf("/"); }else if(mid_line){ printf("-"); }else if(right_slope){ printf("\\"); }else{ printf(" "); } } printf("\n"); } } // middle if(N%2==0) { for(int32_t i = 0; i < L - 1; i++) { printf(" "); } printf("*"); for(int32_t i = 0; i < L - 2; i++) { printf("-"); } } printf("*"); for(int32_t i = 0; i < (N - 1) / 2 * 2; i++) { for(int32_t j = 0; j < 3 * L - 4; j++) { printf(" "); } printf("*"); for(int32_t j = 0; j < L - 2; j++) { printf("-"); } printf("*"); } for(int32_t j = 0; j < 3 * L - 4; j++) { printf(" "); } printf("*"); if(N%2==0) { for(int32_t i = 0; i < L - 2; i++) { printf("-"); } printf("*"); } printf("\n"); // lower for(int32_t outi = 2*N-1; outi >= 1; outi --){ int32_t outj = outi; for(int32_t inni = 0; inni < L-1; inni ++){ int32_t base = 1+(N-outi)*(2*L-2); for(int32_t j = 0; j < base; j ++){ printf(" "); } for(int32_t innj = base; innj < base+outj*(4*L-4); innj ++){ if(innj < 0 || innj >= max_width){ continue; } int32_t basej = (innj - base)%(4*L-4); int32_t basei = (L-2)-inni; bool right_slope = basei+basej==(L-2), mid_line = (basei==0 && basej >= L-2 && basej <= L-2+L-1 ), left_slope = basej-basei==2*L-3; if(left_slope + mid_line + right_slope >= 2){ printf("*"); }else if(left_slope){ printf("/"); }else if(mid_line){ printf("-"); }else if(right_slope){ printf("\\"); }else{ printf(" "); } } printf("\n"); } } } ``` ## 2.6 Bonus: What Happens?? 在不同類型的型別進行加法運算時,會依據其 rank 較高者先進行轉型,rank 高低如下,以下只列出整數型別部分 1. 記憶體儲存較大者 rank 較高,如 int32_t > uint16_t 2. 在相同記憶體大小情況下,unsigned 者較高,如 uint32_t > int32_t 而在 ui + si 進行運算時, ui(uint32_t) rank > si(int32_t) rank,因此 si 會被轉型為 uint32_t,但由於 -1 無法被 uint32_t 表示,因此會透過重複加或是減「新型別的最大值+1」,直到數字可以存入新型別中。所以 si 變成 (-1) + (4294967295 + 1) = 4294967295 ,因此最終的加法為 0 + 4294967295 = 4294967295 而同理,在進行 us + si 時,us(uint16_t) rank < si(int32_t) rank,因此 us 會被轉型為 int32_t,而 0 可以在 int32_t 被直接表示,所以最終加法會去 0 + (-1) = -1