math y debug: Utilidades matemáticas y diagnóstico
Utilice funciones matemáticas con verificación de rango y salida de diagnóstico.
Wave Foundation
Función entera para verificar el rango
std::math::int
min_i32(a: i32, b: i32) -> i32
max_i32(a: i32, b: i32) -> i32
abs_i32_checked(x: i32) -> MathResult<i32>
clamp_i32_checked(x: i32, lo: i32, hi: i32) -> MathResult<i32>
div_floor_i32_checked(a: i32, b: i32) -> MathResult<i32>
div_ceil_i32_checked(a: i32, b: i32) -> MathResult<i32>
MathResult<T> contiene value y error. Importe las constantes de error de std::math::result y use value solo después de comprobar error == MATH_ERROR_NONE. El valor absoluto del mínimo entero con signo no se puede representar con el mismo tipo, por lo que la función de valor absoluto con comprobación informa de un error. clamp rechaza lo > hi. La división comprueba si el divisor es cero o si el resultado desborda el rango. floor y ceil redondean de forma distinta a la división entera, que trunca hacia cero.
Clasificación de valores de punto flotante
is_nan_f64, is_infinite_f64 y is_finite_f64 en std::math::float distinguen valores especiales. También se proporciona la función f32. float_to_bits_f64(value: f64) -> u64 es una función para obtener bits de almacenamiento y es diferente de la conversión numérica de value as u64. NaN ni siquiera es igual a sí mismo, por lo que no se compara con value == nan.
diagnostico
debug_assert(condition: bool, message: str) en std::debug::core finaliza después de diagnosticar una condición falsa. Las situaciones que normalmente pueden fallar, como la entrada del usuario, se manejan con el valor del resultado y assert se usa al verificar las condiciones internas del programa que deben cumplirse.
Guarde el programa a continuación como main.wave y ejecútelo.
import("std::math::int")::{
min_i32, max_i32
};
import("std::debug::core")::{
debug_assert
};
fun main() {
var low: i32 = min_i32(9, 4);
var high: i32 = max_i32(9, 4);
debug_assert(low <= high, "invalid range");
println("{} {}", low, high);
}
Resultado de la ejecución:
4 9
Dirección de redondeo para división negativa
Compare cómo dividir -7 entre 3. / se trunca hacia 0 para convertirse en -2. floor selecciona el entero más pequeño -3 y ceil selecciona el entero más grande -2.
import("std::math::int")::{
div_floor_i32_checked,
div_ceil_i32_checked,
abs_i32_checked
};
import("std::math::result")::{
MathResult,
MATH_ERROR_NONE,
MATH_ERROR_OVERFLOW
};
fun main() -> i32 {
var floor: MathResult<i32> = div_floor_i32_checked(-7, 3);
var ceil: MathResult<i32> = div_ceil_i32_checked(-7, 3);
if (floor.error != MATH_ERROR_NONE || ceil.error != MATH_ERROR_NONE) {
return 1;
}
println("truncate={} floor={} ceil={}", -7 / 3, floor.value, ceil.value);
var absolute: MathResult<i32> = abs_i32_checked(-2147483648);
if (absolute.error == MATH_ERROR_OVERFLOW) {
println("absolute value is outside i32");
}
return 0;
}
Resultado de la ejecución:
truncate=-2 floor=-3 ceil=-2
absolute value is outside i32
Si solo comprueba el valor del resultado, no podrá distinguir entre el valor sustitutivo incluido en caso de fallo y el resultado del cálculo real. Siga primero el orden de verificación error. floor es útil cuando se colocan coordenadas negativas en un intervalo de cierto tamaño, y ceil es útil cuando se redondea el número requerido de paquetes.
¿Qué errores debo manejar?
| situación | error | Ejemplo de procesamiento |
|---|---|---|
| dividir por cero | MATH_ERROR_DIVIDE_BY_ZERO |
Toma de nuevo el denominador |
| El resultado no se puede almacenar en tipo | MATH_ERROR_OVERFLOW |
Calcule con un tipo más amplio o rechace la entrada |
| El mínimo es mayor que el máximo en clamp | MATH_ERROR_INVALID_ARGUMENT |
Modificar rango de configuración |
assert no es una herramienta de reparación de errores. Los errores en la entrada del usuario se manejan mediante declaraciones condicionales y valores de retorno, y después de completar el cálculo, las condiciones internas que deben cumplirse se verifican con debug_assert.