"Can you just write a ** b in Rust?" — You ask and... you'd be wrong
\n\nIf you come to Rust from Python, the first shock is the absence of the ** operator. The second shock is that the compiler does not forgive liberties with types. The third (pleasant) one is that Rust offers a whole arsenal of tools for exponentiation, each tailored to a specific task.
In 2025, when Rust is actively displacing C++ in high-load systems and embedded development, the question "How to raise a number to a power?" (which has gathered thousands of views on Stack Overflow) has become even more relevant. Let's figure it out once and for all: how to correctly, quickly, and safely raise numbers to a power in Rust.
\n\nWhy is there no ** operator in Rust?
\n\nRust is a systems language. It does not allow operator overloading "on the fly" (although the std::ops traits exist, there are none for exponentiation). Instead, the developers proposed method-functions that explicitly indicate the type of operation. This eliminates confusion between integer exponentiation and floating-point arithmetic.
The key rule: choose the method based on the data type. Do not try to raise an i32 to an f64 power — the compiler will not understand you, and if it does (through casting), you risk losing performance or precision.
The pow() method — the king of integers
\n\nThe most popular way for i32, u64, and other integer types:
fn main() {\n let base: i32 = 5;\n let exponent: u32 = 3;\n let result = base.pow(exponent);\n println!("5^3 = {}", result); // 125\n}\n\nNote: the exponent must always be u32 (unsigned). This is logical — the exponent cannot be negative for integers (otherwise you would get a fraction).
When to use: always for integer calculations. It works fast, without allocations, at the level of machine instructions.
\n\nWhat if the exponent is negative?
\nFor integers — no way. Rust does not support negative exponents for integer types because the result would be fractional. If you need 2^-3 — switch to floating-point numbers.
powi() — the ideal choice for f64 and f32
\n\nThis method takes an integer exponent (type i32) but works with floating-point numbers:
fn main() {\n let base: f64 = 2.0;\n let result = base.powi(-3);\n println!("2.0^-3 = {}", result); // 0.125\n\n // Can also use a positive exponent\n let result2 = base.powi(10);\n println!("2.0^10 = {}", result2); // 1024.0\n}\n\n2025 feature: powi() is optimized for integer exponents. It uses the exponentiation by squaring algorithm. If your exponent is a constant or an integer, this is the fastest way for f64/f32.
powf() — when the exponent is also a fraction
\n\nIf both the base and the exponent are floating-point numbers, use powf():
fn main() {\n let base: f64 = 9.0;\n let exponent: f64 = 0.5;\n let result = base.powf(exponent);\n println!("9.0^0.5 = {}", result); // 3.0 (square root)\n\n // Complex case\n let base2 = 2.0_f64;\n let exp2 = 3.14_f64;\n println!("2.0^3.14 = {}", base2.powf(exp2)); // ~8.815\n}\n\nImportant: powf() uses a slow but accurate math library (usually libm or a hardware instruction). For graphics or games where speed matters, consider powi().
The num crate — a universal soldier
\n\nIn 2025, the Rust ecosystem offers the num crate (and num-