MCPcopy Index your code
hub / github.com/RustPython/RustPython / round_float_digits

Function round_float_digits

crates/common/src/float_ops.rs:206–267  ·  view source on GitHub ↗
(x: f64, ndigits: i32)

Source from the content-addressed store, hash-verified

204}
205
206pub fn round_float_digits(x: f64, ndigits: i32) -> Option<f64> {
207 let float = if ndigits.is_zero() {
208 let fract = x.fract();
209 if (fract.abs() - 0.5).abs() < f64::EPSILON {
210 if x.trunc() % 2.0 == 0.0 {
211 x - fract
212 } else {
213 x + fract
214 }
215 } else {
216 x.round()
217 }
218 } else {
219 const NDIGITS_MAX: i32 =
220 ((f64::MANTISSA_DIGITS as i32 - f64::MIN_EXP) as f64 * f64::consts::LOG10_2) as i32;
221 const NDIGITS_MIN: i32 = -(((f64::MAX_EXP + 1) as f64 * f64::consts::LOG10_2) as i32);
222 if ndigits > NDIGITS_MAX {
223 x
224 } else if ndigits < NDIGITS_MIN {
225 0.0f64.copysign(x)
226 } else {
227 let (y, pow1, pow2) = if ndigits >= 0 {
228 // according to cpython: pow1 and pow2 are each safe from overflow, but
229 // pow1*pow2 ~= pow(10.0, ndigits) might overflow
230 let (pow1, pow2) = if ndigits > 22 {
231 (10.0.powf((ndigits - 22) as f64), 1e22)
232 } else {
233 (10.0.powf(ndigits as f64), 1.0)
234 };
235 let y = (x * pow1) * pow2;
236 if !y.is_finite() {
237 return Some(x);
238 }
239 (y, pow1, Some(pow2))
240 } else {
241 let pow1 = 10.0.powf((-ndigits) as f64);
242 (x / pow1, pow1, None)
243 };
244 let z = y.round();
245 #[allow(clippy::float_cmp)]
246 let z = if (y - z).abs() == 0.5 {
247 2.0 * (y / 2.0).round()
248 } else {
249 z
250 };
251 let z = if let Some(pow2) = pow2 {
252 // ndigits >= 0
253 (z / pow2) / pow1
254 } else {
255 z * pow1
256 };
257
258 if !z.is_finite() {
259 // overflow
260 return None;
261 }
262
263 z

Callers 1

__round__Method · 0.85

Calls 5

absMethod · 0.80
truncMethod · 0.80
SomeClass · 0.50
is_zeroMethod · 0.45
is_finiteMethod · 0.45

Tested by

no test coverage detected