reglas redondeo redondear online numeros numero milesimas milesima ejercicios decimales decima como centesimas centesima aproximacion ala c# math decimal rounding

c# - redondeo - Redondea un número decimal a la primera posición decimal que no sea cero



redondear decimales online (5)

Algo como eso ?

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); }

Quiero acortar un número al primer dígito significativo que no es 0. Los dígitos detrás deben redondearse.

Ejemplos:

0.001 -> 0.001 0.00367 -> 0.004 0.00337 -> 0.003 0.000000564 -> 0.0000006 0.00000432907543029 -> 0.000004

Actualmente tengo el siguiente procedimiento:

if (value < (decimal) 0.01) { value = Math.Round(value, 4); }

Nota:

  • los números siempre serán positivos
  • El número de dígitos significativos siempre será 1.
  • los valores mayores 0.01 siempre se redondearán a dos lugares decimales, por lo tanto, si <0.01

Como puede ver en los ejemplos anteriores, un redondeo a 4 posiciones decimales puede no ser suficiente y el valor puede variar mucho.


El código es de R pero el algo debería ser obvio.

> x = 0.0004932 > y = log10(x) > z = ceiling(y) > a = round(10^(y-z),1) > finally = a*10^(z) > finally [1] 5e-04

lo siguiente fue básicamente ya proporcionado por Benjamin K

A riesgo de ser etiquetado como un completo loco, me alegraría anunciar que regexp es tu amigo. Convierta su número en una cadena de caracteres, busque la ubicación del primer carácter que no sea "." ni "0", tome el carácter en esa ubicación y el siguiente carácter detrás de él, conviértalos a un número, redondee y (porque fue cuidadoso), multiplique el resultado por $ 10 ^ {- (número de ceros que encontró entre " . "y el primer número)} $


Otro enfoque

decimal RoundToFirstNonNullDecimal(decimal value) { var nullDecimals = value.ToString().Split(''.'').LastOrDefault()?.TakeWhile(c => c == ''0'').Count(); var roundTo = nullDecimals.HasValue && nullDecimals >= 1 ? nullDecimals.Value + 1 : 2; return Math.Round(value, roundTo); }

Resultado

Console.WriteLine(RoundToFirstNonNullDecimal(0.001m)); 0.001 Console.WriteLine(RoundToFirstNonNullDecimal(0.00367m)); 0.004 Console.WriteLine(RoundToFirstNonNullDecimal(0.000000564m)); 0.0000006 Console.WriteLine(RoundToFirstNonNullDecimal(0.00000432907543029m)); 0.000004 Console.WriteLine(RoundToFirstNonNullDecimal(0.12m)); 0.12 Console.WriteLine(RoundToFirstNonNullDecimal(1.232m)); 1.23 Console.WriteLine(RoundToFirstNonNullDecimal(7)); 7.00


Yo declararía la variable de precision y utilizaría una iteración que multiplica esa variable por 10 con el valor original que no alcanzó, esa precision agregará 1 .

luego use la variable de precision ser Math.Round segundo parámetro.

static decimal RoundFirstSignificantDigit(decimal input) { int precision = 0; var val = input; while (Math.Abs(val) < 1) { val *= 10; precision++; } return Math.Round(input, precision); }

Escribiría un método de extensión para esta función.

public static class FloatExtension { public static decimal RoundFirstSignificantDigit(this decimal input) { int precision = 0; var val = input; while (Math.Abs(val) < 1) { val *= 10; precision++; } return Math.Round(input, precision); } }

entonces usa como

decimal input = 0.00001; input.RoundFirstSignificantDigit();

c # en línea

Resultado

(-0.001m).RoundFirstSignificantDigit() -0.001 (-0.00367m).RoundFirstSignificantDigit() -0.004 (0.000000564m).RoundFirstSignificantDigit() 0.0000006 (0.00000432907543029m).RoundFirstSignificantDigit() 0.000004


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);