FIX: Fixes ROUND, ROUNDUP and ROUNDDOWN behaviour

This commit is contained in:
Nicolás Hatcher
2025-08-08 18:34:40 +02:00
committed by Nicolás Hatcher Andrés
parent 71d6a3d66c
commit f2cb05d7bf
3 changed files with 22 additions and 3 deletions

View File

@@ -2,6 +2,7 @@ use crate::cast::NumberOrArray;
use crate::constants::{LAST_COLUMN, LAST_ROW};
use crate::expressions::parser::ArrayNode;
use crate::expressions::types::CellReferenceIndex;
use crate::number_format::to_precision;
use crate::single_number_fn;
use crate::{
calc_result::CalcResult, expressions::parser::Node, expressions::token::Error, model::Model,
@@ -311,7 +312,7 @@ impl Model {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_number(&args[0], cell) {
Ok(f) => f,
Ok(f) => to_precision(f, 15),
Err(s) => return s,
};
let number_of_digits = match self.get_number(&args[1], cell) {
@@ -327,12 +328,13 @@ impl Model {
let scale = 10.0_f64.powf(number_of_digits);
CalcResult::Number((value * scale).round() / scale)
}
pub(crate) fn fn_roundup(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
if args.len() != 2 {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_number(&args[0], cell) {
Ok(f) => f,
Ok(f) => to_precision(f, 15),
Err(s) => return s,
};
let number_of_digits = match self.get_number(&args[1], cell) {
@@ -352,12 +354,13 @@ impl Model {
CalcResult::Number((value * scale).floor() / scale)
}
}
pub(crate) fn fn_rounddown(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
if args.len() != 2 {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_number(&args[0], cell) {
Ok(f) => f,
Ok(f) => to_precision(f, 15),
Err(s) => return s,
};
let number_of_digits = match self.get_number(&args[1], cell) {

View File

@@ -55,6 +55,7 @@ mod test_arrays;
mod test_escape_quotes;
mod test_extend;
mod test_fn_fv;
mod test_fn_round;
mod test_fn_type;
mod test_frozen_rows_and_columns;
mod test_geomean;

View File

@@ -0,0 +1,15 @@
#![allow(clippy::unwrap_used)]
use crate::test::util::new_empty_model;
#[test]
fn fn_round_approximation() {
let mut model = new_empty_model();
model._set("A1", "=ROUND(1.05*(0.0284+0.0046)-0.0284,4)");
model._set("A2", "=ROUNDDOWN(1.05*(0.0284+0.0046)-0.0284,5)");
model.evaluate();
assert_eq!(model._get_text("A1"), *"0.0063");
assert_eq!(model._get_text("A2"), *"0.00625");
}