Last active
September 26, 2020 09:32
-
-
Save chongkong/efbe0c1bbabbc08d461e4d067fc39030 to your computer and use it in GitHub Desktop.
Code feedback for ibaesuyeon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <math.h> | |
// Consistent code styling is important. | |
// This is my preference, but I uses "2 spaces" for indentation | |
// (as opposed to using "tab") because github renders tab with 8 spaces. | |
// You can configure your code editor to use spaces instead of tab, | |
// even when you're pressing a tab. | |
// Recursive style factorial function. Returns x!. | |
long long factorial(int x) { | |
// "LL" in 1LL is the literal suffix to use the long long value. | |
// See https://boycoding.tistory.com/155. | |
return (x <= 1) ? 1LL : (long long)(x) * factorial(x - 1); | |
} | |
// Recursive style power function. Returns x^exp. | |
double power(double x, int exp) { | |
return (exp <= 0) ? 1.0 : x * power(x, exp - 1); | |
} | |
// sin(x) taylor approximation with naive implementation. | |
double sin_taylor_naive(double rad, int max_order) { | |
// fmod is a modular operation for floating point value (thus the name fmod). | |
// Clip values outside -pi <= rad <= pi. | |
rad = fmod(rad, M_PI); | |
double result = 0.0; | |
for (int k = 1; k <= max_order; k += 2) { | |
// "Sign" is a computer science term whether the value is positive or negative. | |
double sign = (k % 4 == 3) ? -1 : 1; | |
// Large value divided by large value is numerically unstable. | |
result += sign * power(rad, k) / factorial(k); | |
// Un-comment below to see how coefficients goes Inf or NaN when k is big. | |
// printf("DEBUG: k=%d sign=%1.0lf power=%lf coef=%lf\n", | |
// k, sign, power(rad, k), 1.0 / factorial(k)); | |
} | |
return result; | |
} | |
// sin(x) taylor approximation with FMA (Fused multiplication-addition) | |
// implementation. | |
double sin_taylor_fma(double rad, int max_order) { | |
rad = fmod(rad, M_PI); // Clip values outside -pi <= rad <= pi. | |
double result = 1.0; | |
// Taylor expansion for sin(x) has only odd-order terms. | |
if (max_order % 2 == 0) max_order -= 1; | |
for (int k = max_order; k > 1; k -= 2) { | |
result = 1.0 - rad * rad / ((k - 1) * k) * result; | |
} | |
result *= rad; | |
return result; | |
} | |
int main() { | |
double degree; | |
int max_taylor_order; | |
// We use "Enter" instead of "Inject" on interactive command line program. | |
printf("Enter the degree of sine: "); | |
scanf("%lf", °ree); // Note | |
printf("Enter the maximum taylor expansion order: "); | |
scanf("%d", &max_taylor_order); | |
double rad = degree * M_PI / 180.0; // We have M_PI constant already defined | |
// instead of using 3.14159265... | |
// Print double (lf) with 15 decial digits, which is full decimal precision. | |
printf("sin(x) = %0.15lf\n", sin(rad)); | |
printf("sin_taylor_navie(x) = %0.15lf\n", | |
sin_taylor_naive(rad, max_taylor_order)); | |
printf("sin_taylor_fma(x) = %0.15lf\n", | |
sin_taylor_fma(rad, max_taylor_order)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment