Skip to content

Commit c763bd7

Browse files
authored
Karatsuba Multiplication in R (#241)
1 parent 796582a commit c763bd7

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

mathematics/karatsuba.r

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Multiply two integers using the Karatsuba multiplication algorithm.
2+
# This is a fast multiplication algorithm that uses divide-and-conquer.
3+
#
4+
# Expected inputs:
5+
# - x, y: integer values (positive or negative). Non-integer types are not supported.
6+
# - Negative values are supported.
7+
#
8+
# Output type:
9+
# - Returns a numeric value (double). For very large integers (> ~9e15), precision may be lost.
10+
#
11+
# Limits/assumptions:
12+
# - Uses R’s native double precision arithmetic; not suitable for arbitrary-precision operations.
13+
# - For very large integers, use `gmp::bigz` for exact results.
14+
#
15+
# Time Complexity: O(n^log2(3)) ≈ O(n^1.585)
16+
# Space Complexity: O(n)
17+
#
18+
# Example:
19+
# karatsuba(1234, 5678)
20+
# # [1] 7006652
21+
22+
karatsuba <- function(x, y) {
23+
# ---- Input validation ----
24+
if (!is.numeric(x) || !is.numeric(y) || length(x) != 1 || length(y) != 1) {
25+
stop("Inputs x and y must be single numeric values.")
26+
}
27+
if (!is.finite(x) || !is.finite(y)) {
28+
stop("Inputs must be finite numbers.")
29+
}
30+
if (x != floor(x) || y != floor(y)) {
31+
stop("Inputs must be integers (no decimals).")
32+
}
33+
34+
# Handle sign and absolute values
35+
sgn <- sign(x) * sign(y)
36+
x <- abs(x)
37+
y <- abs(y)
38+
39+
# Base case
40+
if (x < 10 || y < 10) {
41+
return(sgn * (x * y))
42+
}
43+
44+
# ---- Robust digit counting (avoids scientific notation issues) ----
45+
get_digits <- function(v) {
46+
if (v == 0) return(1L)
47+
floor(log10(abs(v))) + 1L
48+
}
49+
50+
n <- max(get_digits(x), get_digits(y))
51+
half <- floor(n / 2)
52+
53+
# ---- Split the numbers ----
54+
high_x <- floor(x / 10^half)
55+
low_x <- x %% 10^half
56+
high_y <- floor(y / 10^half)
57+
low_y <- y %% 10^half
58+
59+
# ---- Recursive calls ----
60+
z0 <- karatsuba(low_x, low_y)
61+
z1 <- karatsuba((low_x + high_x), (low_y + high_y))
62+
z2 <- karatsuba(high_x, high_y)
63+
64+
# ---- Combine results (Karatsuba formula) ----
65+
result <- (z2 * 10^(2 * half)) + ((z1 - z2 - z0) * 10^half) + z0
66+
67+
return(sgn * result)
68+
}
69+
70+
# ---- Example usage ----
71+
# Only runs when script is executed directly, not when sourced/imported
72+
if (sys.nframe() == 0) {
73+
a <- 12345678
74+
b <- 87654321
75+
result <- karatsuba(a, b)
76+
cat(sprintf("Karatsuba(%d, %d) = %.0f\n", a, b, result))
77+
78+
standard_result <- a * b
79+
cat(sprintf("Standard multiplication: %d * %d = %.0f\n", a, b, standard_result))
80+
cat(sprintf("Results match: %s\n", result == standard_result))
81+
82+
cat("\nAdditional test cases:\n")
83+
test_cases <- list(
84+
c(1234, 5678),
85+
c(999, 888),
86+
c(12, 34),
87+
c(123456, 789012),
88+
c(-1234, 5678),
89+
c(-999, -888)
90+
)
91+
92+
for (test in test_cases) {
93+
x <- test[1]
94+
y <- test[2]
95+
karatsuba_result <- karatsuba(x, y)
96+
standard_result <- x * y
97+
cat(sprintf(
98+
"karatsuba(%d, %d) = %.0f (Expected: %.0f, Match: %s)\n",
99+
x, y, karatsuba_result, standard_result,
100+
karatsuba_result == standard_result
101+
))
102+
}
103+
}

0 commit comments

Comments
 (0)