Round a decimal number to the first decimal position that is not zero
var value = 0.000000564;
int cnt = 0;
bool hitNum = false;
var tempVal = value;
while (!hitNum)
{
if(tempVal > 1)
{
hitNum = true;
}
else
{
tempVal *= 10;
cnt++;
}
}
var newValue = (decimal)Math.Round(value, cnt);
Something like that ?
public decimal SpecialRound(decimal value)
{
int posDot = value.ToString().IndexOf('.'); // Maybe use something about cultural (in Fr it's ",")
if(posDot == -1)
return value;
int posFirstNumber = value.ToString().IndexOfAny(new char[9] {'1', '2', '3', '4', '5', '6', '7', '8', '9'}, posDot);
return Math.Round(value, posFirstNumber);
}
I would declare precision
variable and use a iteration multiplies that variable by 10
with the original value it didn't hit, that precision
will add 1
.
then use precision
variable be Math.Round
second parameter.
I had added some modifications to the method which can support not only zero decimal points but also all decimal numbers.
static decimal RoundFirstSignificantDigit(decimal input) {
if(input == 0)
return input;
int precision = 0;
var val = input - Math.Round(input,0);
while (Math.Abs(val) < 1)
{
val *= 10;
precision++;
}
return Math.Round(input, precision);
}
I would write an extension method for this function.
public static class FloatExtension
{
public static decimal RoundFirstSignificantDigit(this decimal input)
{
if(input == 0)
return input;
int precision = 0;
var val = input - Math.Round(input,0);
while (Math.Abs(val) < 1)
{
val *= 10;
precision++;
}
return Math.Round(input, precision);
}
}
then use like
decimal input = 0.00001;
input.RoundFirstSignificantDigit();
c# online
Result
(-0.001m).RoundFirstSignificantDigit() -0.001
(-0.00367m).RoundFirstSignificantDigit() -0.004
(0.000000564m).RoundFirstSignificantDigit() 0.0000006
(0.00000432907543029m).RoundFirstSignificantDigit() 0.000004