fork download
  1. #include <sys/time.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4.  
  5. double getdoubletime() {
  6. struct timeval t;
  7. gettimeofday(&t, NULL);
  8. return (double) t.tv_sec + ((double) t.tv_usec * 1e-6);
  9. }
  10.  
  11. #include <math.h>
  12. #include <stdlib.h>
  13.  
  14. #define N 65536
  15.  
  16. inline double min(double d1, double d2) { return d2 < d1 ? d2 : d1; }
  17. inline double max(double d1, double d2) { return d2 > d1 ? d2 : d1; }
  18.  
  19. double fract_fast(double d) {
  20. // Clamp d to values that are representable 64-bit integers.
  21. // Any double-precision floating-point number outside of this range
  22. // has no fractional part, so these calls to min / max will have
  23. // no effect on the return value of this function.
  24. d = min((double)(((int64_t)1)<<62), d);
  25. d = max(-(double)(((int64_t)1)<<62), d);
  26.  
  27. // C / C++ define casts to integer as always being the round-toward-zero
  28. // of the floating point number, regardless of rounding mode.
  29. int64_t integral_part = (int64_t)d;
  30. return d - (double)integral_part;
  31. }
  32.  
  33. int main(int argc, char const *argv[]) {
  34. size_t i;
  35. double t0;
  36. // generate some random floating-point numbers
  37. double numbers[N];
  38. double fractionals[N];
  39. double meth1[N];
  40. for (i=0; i<N; ++i) {
  41. numbers[i] = rand() + rand() / (double)RAND_MAX;
  42. }
  43. // Throw in some edge cases for good measure
  44. numbers[N - 1] *= -1;
  45. numbers[N - 2] *= 1e30;
  46. numbers[N - 3] *= -1e30;
  47.  
  48. // extract fractional part: method 1
  49. t0 = getdoubletime();
  50. double integral;
  51. for (i=0; i<N; ++i) {
  52. fractionals[i] = modf(numbers[i], &integral);
  53. }
  54. printf("method 1 took %lf seconds (using modf)\n", getdoubletime() - t0);
  55. for (i=0; i<N; ++i) {
  56. meth1[i] = fractionals[i];
  57. }
  58.  
  59. // extract fractional part: method 2
  60. t0 = getdoubletime();
  61. for (i=0; i<N; ++i) {
  62. fractionals[i] = numbers[i] - (long)numbers[i];
  63. }
  64. printf("method 2 took %lf seconds (casting to long)\n", getdoubletime() - t0);
  65. for (i=0; i<N; ++i) {
  66. if (meth1[i] != fractionals[i]) {
  67. printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i, numbers[i], meth1[i], fractionals[i]);
  68. if (i > 20) break;
  69. }
  70. }
  71.  
  72. // extract fractional part: method 3
  73. t0 = getdoubletime();
  74. for (i=0; i<N; ++i) {
  75. fractionals[i] = fract_fast(numbers[i]);
  76. }
  77. printf("method 3 took %lf seconds (using min/max/casts/sub)\n", getdoubletime() - t0);
  78. for (i=0; i<N; ++i) {
  79. if (meth1[i] != fractionals[i]) {
  80. printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i, numbers[i], meth1[i], fractionals[i]);
  81. if (i > 20) break;
  82. }
  83. }
  84.  
  85. // extract fractional part: method 4
  86. t0 = getdoubletime();
  87. for (i=0; i<N; ++i) {
  88. fractionals[i] = numbers[i] - floor(numbers[i]);
  89. }
  90. printf("method 4 took %lf seconds (using floor)\n", getdoubletime() - t0);
  91. for (i=0; i<N; ++i) {
  92. if (meth1[i] != fractionals[i]) {
  93. printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i, numbers[i], meth1[i], fractionals[i]);
  94. if (i > 20) break;
  95. }
  96. }
  97.  
  98. // extract fractional part: method 5
  99. t0 = getdoubletime();
  100. for (i=0; i<N; ++i) {
  101. fractionals[i] = fmod(numbers[i], 1.0);
  102. }
  103. printf("method 5 took %lf seconds (using fmod)\n", getdoubletime() - t0);
  104. for (i=0; i<N; ++i) {
  105. if (meth1[i] != fractionals[i]) {
  106. printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i, numbers[i], meth1[i], fractionals[i]);
  107. if (i > 20) break;
  108. }
  109. }
  110.  
  111. // extract fractional part: method 6
  112. t0 = getdoubletime();
  113. for (i=0; i<N; ++i) {
  114. fractionals[i] = remainder(numbers[i], 1.0);
  115. }
  116. printf("method 6 took %lf seconds (using remainder)\n", getdoubletime() - t0);
  117. for (i=0; i<N; ++i) {
  118. if (meth1[i] != fractionals[i]) {
  119. printf("Mismatch at %d: frac(%.12g) expected %.12g, got %.12g\n", (int)i, numbers[i], meth1[i], fractionals[i]);
  120. if (i > 20) break;
  121. }
  122. }
  123.  
  124. return 0;
  125. }
  126.  
Success #stdin #stdout 0.02s 5436KB
stdin
Standard input is empty
stdout
method 1 took 0.000449 seconds (using modf)
method 2 took 0.000074 seconds (casting to long)
Mismatch at 65533: frac(-9.27517998277e+38) expected -0, got -9.27517998277e+38
method 3 took 0.000136 seconds (using min/max/casts/sub)
method 4 took 0.000175 seconds (using floor)
Mismatch at 65535: frac(-20429118.6606) expected -0.66055546701, got 0.33944453299
method 5 took 0.008163 seconds (using fmod)
method 6 took 0.001427 seconds (using remainder)
Mismatch at 1: frac(1681692777.8) expected 0.798439979553, got -0.201560020447
Mismatch at 3: frac(719885386.768) expected 0.768229603767, got -0.231770396233
Mismatch at 4: frac(596516649.554) expected 0.553969979286, got -0.446030020714
Mismatch at 5: frac(1025202362.63) expected 0.62887096405, got -0.37112903595
Mismatch at 6: frac(783368690.513) expected 0.513400912285, got -0.486599087715
Mismatch at 7: frac(2044897763.92) expected 0.91619515419, got -0.0838048458099
Mismatch at 8: frac(1365180540.72) expected 0.71729683876, got -0.28270316124
Mismatch at 9: frac(304089172.607) expected 0.6069688797, got -0.3930311203
Mismatch at 11: frac(294702567.804) expected 0.804176747799, got -0.195823252201
Mismatch at 15: frac(1101513929.84) expected 0.839112281799, got -0.160887718201
Mismatch at 17: frac(1369133069.52) expected 0.524287223816, got -0.475712776184
Mismatch at 18: frac(1059961393.97) expected 0.972774982452, got -0.0272250175476
Mismatch at 19: frac(628175011.771) expected 0.771357655525, got -0.228642344475
Mismatch at 20: frac(1131176229.77) expected 0.769913911819, got -0.230086088181
Mismatch at 21: frac(859484421.892) expected 0.89152944088, got -0.10847055912