Тип Rust's f64
предоставляет функцию round()
, которая округляется до ближайшего целого числа, но возвращает f64
. Java Math.round(double)
, с другой стороны, возвращает long
. Я могу позвонить round()
, а затем отправить на i64
, но это гарантирует, что я получу правильный результат? Здесь «правильный» означает получение ближайшего i64
- Java round()
возвращает «ближайший длинный».Округление f64 до ближайшего i64 в Rust
ответ
От the book конверсии с плавающей точкой на целые типы округлены к нулю, поэтому округление сначала почти правильно: f.round() as i64
.
Однако в настоящее время это неопределенное поведение (но это a bug), если f64
находится за пределами допустимого диапазона (огромная величина) i64
. Поэтому сначала нужно закрепить значение (или, возможно, лучше, поднять ошибку или утвердить). , Возможно, очевидный ответ не работает:
f.max(std::i64::MIN as f64).min(std::i64::MAX as f64).round() as i64
потому, что превращения i64::MAX
в f64
не точны, и применяя выше 1e100
заканчивается с большим отрицательным значением (в моем тесте, как уже упоминалось, это на самом деле не определено).
Лучшим вариантом является возвращение некоторой ошибки, если значение с плавающей запятой выходит за пределы разумного диапазона, ожидаемого вашим приложением.
Кажется, вам нужен способ получить нижний и верхний пределы смежного диапазона интегральных значений, который вписывается в 'f64', чтобы иметь возможность зажимать или создавать исключение. В противном случае из-за неопределенного поведения вы не сможете проверить конверсию. Возможно, язык должен раскрывать [те] (http://stackoverflow.com/questions/3793838/which-is-the-first-integer-that-an-ieee-754-float-is-incapable-of-representing-e). –
Согласен, в общем случае. Но, вероятно, есть предел ниже тех, что имеет смысл для любого (нормально, самого) данного приложения. –
Учитывая, что речь идет о 2 , да, есть, вероятно, хороший предел! –
Вы можете использовать conv
клети для этого:
use conv::prelude::*;
let x = 9_223_371_487_098_961_920i64 as f64;
println!("{:?}", x.approx_as_by::<i64, RoundToNearest>());
// Ok(9223371487098962944)
let x = 9_223_372_036_854_775_807i64 as f64;
println!("{:?}", x.approx_as_by::<i64, RoundToNearest>());
// Err(FloatError::PosOverflow(..))
Вот простой «на обратной стороне конверта» реализация:
const INTEGRAL_LIMIT: f64 = 9007199254740992.0;
#[derive(Debug, PartialEq, Eq)]
enum Error {
NaN,
Overflow,
Underflow,
}
fn try_from(f: f64) -> Result<i64, Error> {
let f = f.round();
if f.is_nan() { return Err(Error::NaN); }
if f < -INTEGRAL_LIMIT { return Err(Error::Underflow); }
if f > INTEGRAL_LIMIT { return Err(Error::Overflow); }
Ok(f as i64)
}
И он приходит с минимальным набором тестов, который проходит:
fn main() {
assert_eq!(try_from(std::f64::NAN), Err(Error::NaN));
assert_eq!(try_from(std::f64::NEG_INFINITY), Err(Error::Underflow));
assert_eq!(try_from(-9007199254740994.0), Err(Error::Underflow));
assert_eq!(try_from(9007199254740994.0), Err(Error::Overflow));
assert_eq!(try_from(std::f64::INFINITY), Err(Error::Overflow));
assert_eq!(try_from(-INTEGRAL_LIMIT), Ok(-9007199254740992));
assert_eq!(try_from(INTEGRAL_LIMIT), Ok(9007199254740992));
}
Я действительно ожидал TryFrom
implementa чтобы быть доступным, но не нашел ни одного.
- 1. Округление до ближайшего доллара
- 2. Округление до ближайшего 100
- 3. Строка parse для f64 и i64
- 4. Цена Округление до ближайшего 5с
- 5. Округление до ближайшего 500, Python
- 6. Округление до ближайшего, учитывая уровень
- 7. число Округление до ближайшего интервала
- 8. C# - Округление до ближайшего целого
- 9. Округление Механизм до ближайшего 0,05
- 10. Сделайте округление до ближайшего значения
- 11. округление до ближайшего числа рубина
- 12. округление число до ближайшего 9
- 13. Округление значения до ближайшего 50
- 14. Округление до ближайшего усеченного 100
- 15. Java округление до ближайшего 0.05
- 16. округление до ближайшего нуля, побитовое
- 17. Округление до ближайшего целого числа
- 18. Python - округление до ближайшего 05
- 19. Округление до ближайшего высшего целого в VBA
- 20. Округление до ближайшего 0.05 в JavaScript
- 21. Округление до ближайшего или вверх в SQLite
- 22. Округление до ближайшего 0.5 в matlab
- 23. Округление числа до ближайшего 10 в Postgres
- 24. Округление до ближайшего 5/10 в PHP
- 25. округление раз до ближайшего часа в R
- 26. Округление Дата до ближайшего дня в Javascript.
- 27. Округление NSDate до ближайшего часа в прошивкой
- 28. округление до ближайшего цента в уже
- 29. Округление проектора до ближайшего целого числа - VB.NET
- 30. побитовое округление округления до ближайшего нуля
Что вы хотите, если 'f64' является интегральным, но выходит за пределы диапазона' i64'? –
@ChrisEmerson в этом случае Java кажется круглым '1e100' до' 9223372036854775807'. – Shepmaster