diff --git a/src/real.cpp b/src/real.cpp
index ff8579e5..35b2b604 100644
--- a/src/real.cpp
+++ b/src/real.cpp
@@ -685,6 +685,26 @@ real ceil(real const &x)
         return ret + real::R_1;
 }
 
+real round(real const &x)
+{
+    if (x < real::R_0)
+        return -round(-x);
+
+    return floor(x + (real::R_1 >> 1));
+}
+
+real fmod(real const &x, real const &y)
+{
+    if (!y)
+        return real::R_0; /* FIXME: return NaN */
+
+    if (!x)
+        return x;
+
+    real tmp = round(x / y);
+    return x - tmp * y;
+}
+
 real sin(real const &x)
 {
     real ret = 0.0, fact = 1.0, xn = x, x2 = x * x;
diff --git a/src/real.h b/src/real.h
index e88707a5..c12738dc 100644
--- a/src/real.h
+++ b/src/real.h
@@ -71,6 +71,8 @@ public:
 
     friend real floor(real const &x);
     friend real ceil(real const &x);
+    friend real round(real const &x);
+    friend real fmod(real const &x, real const &y);
 
     friend real sin(real const &x);
     friend real cos(real const &x);
diff --git a/test/unit/real.cpp b/test/unit/real.cpp
index cf482789..93e17120 100644
--- a/test/unit/real.cpp
+++ b/test/unit/real.cpp
@@ -257,42 +257,45 @@ LOLUNIT_FIXTURE(RealTest)
         }
     }
 
-    LOLUNIT_TEST(FloorCeil)
+    LOLUNIT_TEST(FloorCeilEtc)
     {
         double tests[] =
         {
-            -2.0,  -2.0, -2.0,
-            -1.5,  -2.0, -1.0,
-            -1.0,  -1.0, -1.0,
-            -0.0,  -0.0, -0.0,
-             0.0,   0.0,  0.0,
-             0.25,  0.0,  1.0,
-             0.375, 0.0,  1.0,
-             0.5,   0.0,  1.0,
-             1.0,   1.0,  1.0,
-             1.5,   1.0,  2.0,
-             2.0,   2.0,  2.0,
-             2.5,   2.0,  3.0,
-             3.0,   3.0,  3.0,
-            8192.0,     8192.0, 8192.0,
-            8192.03125, 8192.0, 8193.0,
-            8192.5,     8192.0, 8193.0,
-            8193.0,     8193.0, 8193.0,
-            549755813888.0,     549755813888.0, 549755813888.0,
-            549755813888.03125, 549755813888.0, 549755813889.0,
-            549755813888.5,     549755813888.0, 549755813889.0,
-            549755813889.0,     549755813889.0, 549755813889.0,
+            -2.0,  -2.0, -2.0,  -2.0,
+            -1.5,  -2.0, -1.0,  -2.0,
+            -1.0,  -1.0, -1.0,  -1.0,
+            -0.0,  -0.0, -0.0,  -0.0,
+             0.0,   0.0,  0.0,   0.0,
+             0.25,  0.0,  1.0,   0.0,
+             0.375, 0.0,  1.0,   0.0,
+             0.5,   0.0,  1.0,   1.0,
+             1.0,   1.0,  1.0,   1.0,
+             1.5,   1.0,  2.0,   2.0,
+             2.0,   2.0,  2.0,   2.0,
+             2.5,   2.0,  3.0,   3.0,
+             3.0,   3.0,  3.0,   3.0,
+            8192.0,     8192.0, 8192.0, 8192.0,
+            8192.03125, 8192.0, 8193.0, 8192.0,
+            8192.5,     8192.0, 8193.0, 8193.0,
+            8193.0,     8193.0, 8193.0, 8193.0,
+            549755813888.0,     549755813888.0, 549755813888.0, 549755813888.0,
+            549755813888.03125, 549755813888.0, 549755813889.0, 549755813888.0,
+            549755813888.5,     549755813888.0, 549755813889.0, 549755813889.0,
+            549755813889.0,     549755813889.0, 549755813889.0, 549755813889.0,
         };
 
-        for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n += 3)
+        for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n += 4)
         {
             double a0 = floor((real)tests[n]);
             double b0 = tests[n + 1];
             double a1 = ceil((real)tests[n]);
             double b1 = tests[n + 2];
+            double a2 = round((real)tests[n]);
+            double b2 = tests[n + 3];
 
             LOLUNIT_ASSERT_EQUAL(b0, a0);
             LOLUNIT_ASSERT_EQUAL(b1, a1);
+            LOLUNIT_ASSERT_EQUAL(b2, a2);
         }
     }
 };