From 90810fef243e30e285df79576ac3f8f55c890aaf Mon Sep 17 00:00:00 2001 From: erwinpan1 Date: Wed, 12 Jul 2023 18:54:39 +0800 Subject: [PATCH 1/4] Workaround Fan Percent Setting floating point err Workaround floating point precision error which will cause invalid value after ceil() For example, the current value: speedMax: 10 percent: 70 speedMax * (percent * 0.01) = 7.000000000000001 (floating point precision error) ceil(speedMax * (percent * 0.01)) = 8 => The error propagate to ceil and cause the final result error. --- src/app/clusters/fan-control-server/fan-control-server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 4c70a4a0f02073..327dafa532038b 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -347,7 +347,8 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt ChipLogError(Zcl, "Failed to get SpeedSetting with error: 0x%02x", status)); float percent = percentSetting.Value(); - uint8_t speedSetting = static_cast(ceil(speedMax * (percent * 0.01))); + // Minus insignificant number 0.00000001 before ceil() to avoid floating point precision error + uint8_t speedSetting = static_cast(ceil(speedMax * (percent * 0.01) - 0.00000001)); if (currentSpeedSetting.IsNull() || speedSetting != currentSpeedSetting.Value()) { From 0040b88b1c6c368dd35045de3f5f523c9009d25e Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 12 Jul 2023 11:10:29 +0000 Subject: [PATCH 2/4] Restyled by clang-format --- src/app/clusters/fan-control-server/fan-control-server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 327dafa532038b..d286207c3e8686 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -346,7 +346,7 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(Zcl, "Failed to get SpeedSetting with error: 0x%02x", status)); - float percent = percentSetting.Value(); + float percent = percentSetting.Value(); // Minus insignificant number 0.00000001 before ceil() to avoid floating point precision error uint8_t speedSetting = static_cast(ceil(speedMax * (percent * 0.01) - 0.00000001)); From fdc74b5554bc93bec8edeae625670141212df59c Mon Sep 17 00:00:00 2001 From: erwinpan1 Date: Thu, 13 Jul 2023 13:26:45 +0800 Subject: [PATCH 3/4] Workaround Fan PercentSetting float error (2nd) Use integer multiply & devide to workaround floating point precision error which causes incorrect Fan PercentSetting value after ceil calculation. --- src/app/clusters/fan-control-server/fan-control-server.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index d286207c3e8686..4a04028e910d68 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -346,9 +346,9 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(Zcl, "Failed to get SpeedSetting with error: 0x%02x", status)); - float percent = percentSetting.Value(); - // Minus insignificant number 0.00000001 before ceil() to avoid floating point precision error - uint8_t speedSetting = static_cast(ceil(speedMax * (percent * 0.01) - 0.00000001)); + uint16_t percent = percentSetting.Value(); + // Plus 99 then devide by 100 instead of multiplying 0.01 to workaround floating point precision error + uint8_t speedSetting = static_cast(ceil((speedMax * percent + 99) / 100)); if (currentSpeedSetting.IsNull() || speedSetting != currentSpeedSetting.Value()) { From 66262a3b07afcec23fb9939432ac0143677a68e5 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 13 Jul 2023 09:51:56 -0400 Subject: [PATCH 4/4] Update src/app/clusters/fan-control-server/fan-control-server.cpp Co-authored-by: Boris Zbarsky --- src/app/clusters/fan-control-server/fan-control-server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 4a04028e910d68..eed33820e0a947 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -347,8 +347,8 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt ChipLogError(Zcl, "Failed to get SpeedSetting with error: 0x%02x", status)); uint16_t percent = percentSetting.Value(); - // Plus 99 then devide by 100 instead of multiplying 0.01 to workaround floating point precision error - uint8_t speedSetting = static_cast(ceil((speedMax * percent + 99) / 100)); + // Plus 99 then integer divide by 100 instead of multiplying 0.01 to avoid floating point precision error + uint8_t speedSetting = static_cast((speedMax * percent + 99) / 100); if (currentSpeedSetting.IsNull() || speedSetting != currentSpeedSetting.Value()) {