Problem with decimal floats truncation

Hello,

I’m new to UE4 and just wrote a “Truncate Float after xxx decimals” node. But for some reasons it has a random behavior. Sometimes it works (1/4), but most of the time it doesn’t (3/4), see at the end of the post for the results it produces. I think there is some optimization shenanigans wish screw the math. Here’s the node code

/******************* HEADER *******************/
#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "BlueprintNode_TruncatePrecision.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(TruncatePrecisionNode, Log, All); // for UE_LOG

UCLASS()
class ARDUINO_API UBlueprintNode_TruncatePrecision : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	/** Truncate Precision Node **/
	UFUNCTION(BlueprintPure, meta = (DisplayName = "Truncate Floats with int fixed past coma precision", CompactNodeTitle = "Trunc", Keywords = "truncate floats precision"), Category = "Personal Blueprint Nodes")
	static float TruncatePrecision(float in, int precision);
};



/******************* CPP *******************/
#include "Arduino.h"
#include "BlueprintNode_TruncatePrecision.h"
#include <cmath>
DEFINE_LOG_CATEGORY(TruncatePrecisionNode) // for UE_LOG

/** Truncate Precision Blueprint Node Code **/
float UBlueprintNode_TruncatePrecision::TruncatePrecision(float in, int precision)
{
	//return 0.0f;
	float tmp = std::round(in*(precision * 10)) / (precision * 10); // I tried to use round, floor, ceil, trunc
	UE_LOG( TruncatePrecisionNode, Warning, TEXT("%s"), *FString::Printf(TEXT( "in : %f ; precision : %d ; result : %f"), in, precision, tmp) );
	return tmp;
}

(I know about the flaws of my code, overflow and such, it’s just for learning)
And here are some of the results I got out of it:

TruncatePrecisionNode:Warning: in : 268.381805 ; precision : 1 ; result : 268.399994
TruncatePrecisionNode:Warning: in : 3.556587 ; precision : 1 ; result : 3.600000
TruncatePrecisionNode:Warning: in : 326.243225 ; precision : 1 ; result : 326.200012
TruncatePrecisionNode:Warning: in : 268.381805 ; precision : 1 ; result : 268.399994
TruncatePrecisionNode:Warning: in : -186.618744 ; precision : 1 ; result : -186.600006

My questions are : Is there some hidden optimization I should know about ? Do you have any idea of what could be causing that kind of behavior ? Is anyone still reading this long post ? If so thanks for reading and even more thanks for answering.

The variance looks like floating point precision errors.

If you don’t know about floating point precision, you’ll want to read about it:

http://floating-point-gui.de/

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

The “best” way to work around floating point errors depends entirely on your use case.

Your function is wrong, though. It will only work for precision values of 1. Rather than multiplying by ten, you need ten to the Nth power. (10^1 = 10, 10^2 = 100, 10^3 = 1000, etc.) Otherwise you won’t be moving places.

i.e.

in = 10.54321, precision = 4

4 x 10 = 40

10.54321 x 40 = 421.7284

truncates to: 421

421 / 40 = 10.525


(10^4) = 10000

10.54321 x 10000 = 105432.1

truncates to: 105432

105432 / 10000 = 10.5432