Я хочу декодировать, хранить и кодировать поплавок в Rust. Я знаю о num::Float::integer_decode()
, но я бы предпочел не потерять любую точность. То есть, если формат, который я кодирую, меньше, чем формат, который я кодирую, конечно.Как декодировать и кодировать поплавок в Rust?
ответ
Интерпретировать биты с плавающей точкой как целое и распечатать значение как HEX:
use std::mem;
fn main() {
let a_third: f64 = 1.0/3.0;
let as_int: u64 = unsafe { mem::transmute(a_third) };
println!("{}", as_int);
let as_string = format!("{:016x}", as_int);
println!("{}", as_string);
let back_to_int = u64::from_str_radix(&as_string, 16).expect("Not an integer");
println!("{}", back_to_int);
let back_to_float: f64 = unsafe { mem::transmute(back_to_int) };
println!("{}", back_to_float);
assert_eq!(back_to_float, a_third);
}
Почему бы просто не трансмутировать 'f64' в' [u8; 8] 'и хранить его без ненужных преобразований? –
@PavelStrakhov звучит как главный кандидат на ответ! – Shepmaster
О! Я надеялся, что 'f32' и' f64' будут напрямую кодироваться как шестнадцатеричные (это самый простой способ получить переносимое представление), но, по-видимому, они не реализуют 'LowerHex' или' UpperHex'. Разочарование :( –
Что случилось с integer_decode()
? Это без потерь и работает для конечных чисел, а также NaN и бесконечностей:
use std::mem;
fn integer_decode(val: f64) -> (u64, i16, i8) {
let bits: u64 = unsafe { mem::transmute(val) };
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
let mantissa = if exponent == 0 {
(bits & 0xfffffffffffff) << 1
} else {
(bits & 0xfffffffffffff) | 0x10000000000000
};
exponent -= 1023 + 52;
(mantissa, exponent, sign)
}
fn main() {
println!("{:?}", integer_decode(std::f64::NAN));
println!("{:?}", integer_decode(std::f64::INFINITY));
println!("{:?}", integer_decode(std::f64::NEG_INFINITY));
}
Исходя из документов, которые поставляются с функция, она может потерять точность во время кодирования –
@JeroenBollen вы можете связать эти документы? Я не могу найти эту информацию в 'std'. Я реализовал' fn integer_encode ((mantissa, exponent, sign): (u64, i16, i8)) -> f64 {(знак как f64) * (mantissa as f64) * (2f64.powf (exponent as f64))} 'и он работает для любого' X', который я передаю в 'integer_encode (integer_decode (X)) 'за исключением' NaN' (возможно, что-то не так с моим 'int eger_encode', хотя). – ljedrz
Я сделал ссылку на него в OP. –
Если вы не собираетесь передавать преобразованные в последовательную форму данные между машинами или вы уверены, что представление с плавающей точкой является одинаковым на всех платформах вы нацелены вы можете сохранить представление байт числа:
use std::io::{Read, Write};
fn main() {
{
let num: f64 = 1.0/3.0;
let bytes: [u8; 8] = unsafe { std::mem::transmute(num) };
let mut file = std::fs::File::create("/tmp/1").unwrap();
file.write_all(&bytes).unwrap();
}
{
let mut file = std::fs::File::open("/tmp/1").unwrap();
let mut bytes: [u8; 8] = unsafe { std::mem::uninitialized() };
file.read_exact(&mut bytes).unwrap();
let num: f64 = unsafe { std::mem::transmute(bytes) };
println!("result: {}", num);
}
}
вы также можете использовать существующие рамки сериализации, как serde. Если вы не хотите всю структуру и просто хотите сериализовать поплавки, вы можете использовать dtoa (она используется serde_json), хотя я не уверен, что она обеспечивает надежные гарантии точности.
- 1. Как кодировать и декодировать NSCalendarUnit
- 2. Как декодировать/кодировать «\ uNNNN»
- 3. как Кодировать и декодировать текст в Jsp
- 4. Как кодировать и декодировать RGB в Hex
- 5. Как кодировать и декодировать SecretKey в JAVA?
- 6. Как кодировать и декодировать пароль в symfony2
- 7. Как кодировать и декодировать NSString в iOS?
- 8. кодировать и декодировать символы Юникода как «\ и ####»
- 9. Perl utf8 декодировать и кодировать
- 10. Кодировать и декодировать в Javascript и php
- 11. Как кодировать и декодировать большие значения OID?
- 12. J2ME, как кодировать и декодировать Json?
- 13. Как кодировать и декодировать значение запроса
- 14. Как кодировать и декодировать const char *
- 15. Как кодировать/декодировать между Javascript и ColdFusion?
- 16. Как кодировать/декодировать пустую строку
- 17. Как кодировать и декодировать этот класс
- 18. Как просто кодировать и декодировать строковую переменную
- 19. Как кодировать/декодировать скалярные значения
- 20. как кодировать/декодировать простую строку
- 21. Кодировать и декодировать перечисление в Swift 1.2
- 22. Можно ли кодировать и декодировать в C#?
- 23. кодировать и декодировать данные в C
- 24. кодировать и декодировать Http-запрос в Java
- 25. Как кодировать/декодировать строки в JavaScript?
- 26. Как декодировать/кодировать десятичные значения в python?
- 27. Как кодировать/декодировать CFUUIDRef в Objective-C
- 28. Как кодировать (декодировать) base64 в C?
- 29. Как кодировать/декодировать объекты pojo в Netty?
- 30. Как кодировать/декодировать объекты HTML в Ruby?
'integer_decode()' не теряет точность - это просто деконструкция числа с плавающей запятой в его компонентах. – trentcl
@trentcl Я знаю, но он выглядит как кодировка, как в документации к вышеупомянутой функции. –