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(" \n Additional 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