c# - solo - Truncar dos decimales sin redondear
truncar 2 decimales vb net (15)
¿ ((long)(3.4679 * 100)) / 100.0
daría lo que quiere?
Digamos que tengo un valor de 3.4679 y quiero 3.46, ¿cómo puedo truncar a dos decimales sin redondear?
He intentado lo siguiente, pero los tres me dan 3.47:
void Main()
{
Console.Write(Math.Round(3.4679, 2,MidpointRounding.ToEven));
Console.Write(Math.Round(3.4679, 2,MidpointRounding.AwayFromZero));
Console.Write(Math.Round(3.4679, 2));
}
Esto devuelve 3.46, pero parece sucio de alguna manera:
void Main()
{
Console.Write(Math.Round(3.46799999999 -.005 , 2));
}
¿Que este trabajo para usted?
Console.Write(((int)(3.4679999999*100))/100.0);
Además de las soluciones anteriores, hay otra manera que podemos lograr.
decimal val=23.5678m,finalValue;
//take the decimal part
int decimalPos = val.ToString().IndexOf(''.'');
string decimalPart = val.ToString().Substring(decimalPosition+1,val.ToString().Length);
//will result.56
string wholePart=val.ToString().Substring(0,decimalPos-1);
//concantinate and parse for decimal.
string truncatedValue=wholePart+decimalPart;//"23.56"
bool isDecimal=Decimal.tryParse(truncatedValue,out finalValue);//finalValue=23.56
Aquí está mi implementación de la función TRUNC
private static object Tranc(List<Expression.Expression> p)
{
var target = (decimal)p[0].Evaluate();
// check if formula contains only one argument
var digits = p.Count > 1
? (decimal) p[1].Evaluate()
: 0;
return Math.Truncate((double)target * Math.Pow(10, (int)digits)) / Math.Pow(10, (int)digits);
}
Aquí hay un método de extensión:
public static decimal? TruncateDecimalPlaces(this decimal? value, int places)
{
if (value == null)
{
return null;
}
return Math.Floor((decimal)value * (decimal)Math.Pow(10, places)) / (decimal)Math.Pow(10, places);
} // end
Dejaré la solución para números decimales.
Algunas de las soluciones para decimales aquí son propensas al desbordamiento (si pasamos un número decimal muy grande y el método intentará multiplicarlo).
La solución de Tim Lloyd está protegida del desbordamiento, pero no es demasiado rápida.
La siguiente solución es aproximadamente 2 veces más rápida y no tiene un problema de desbordamiento:
public static class DecimalExtensions
{
public static decimal TruncateEx(this decimal value, int decimalPlaces)
{
if (decimalPlaces < 0)
throw new ArgumentException("decimalPlaces must be greater than or equal to 0.");
var modifier = Convert.ToDecimal(0.5 / Math.Pow(10, decimalPlaces));
return Math.Round(value >= 0 ? value - modifier : value + modifier, decimalPlaces);
}
}
[Test]
public void FastDecimalTruncateTest()
{
Assert.AreEqual(-1.12m, -1.129m. TruncateEx(2));
Assert.AreEqual(-1.12m, -1.120m. TruncateEx(2));
Assert.AreEqual(-1.12m, -1.125m. TruncateEx(2));
Assert.AreEqual(-1.12m, -1.1255m.TruncateEx(2));
Assert.AreEqual(-1.12m, -1.1254m.TruncateEx(2));
Assert.AreEqual(0m, 0.0001m.TruncateEx(3));
Assert.AreEqual(0m, -0.0001m.TruncateEx(3));
Assert.AreEqual(0m, -0.0000m.TruncateEx(3));
Assert.AreEqual(0m, 0.0000m.TruncateEx(3));
Assert.AreEqual(1.1m, 1.12m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.15m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.19m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.111m. TruncateEx(1));
Assert.AreEqual(1.1m, 1.199m. TruncateEx(1));
Assert.AreEqual(1.2m, 1.2m. TruncateEx(1));
Assert.AreEqual(0.1m, 0.14m. TruncateEx(1));
Assert.AreEqual(0, -0.05m. TruncateEx(1));
Assert.AreEqual(0, -0.049m. TruncateEx(1));
Assert.AreEqual(0, -0.051m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.14m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.15m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.16m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.19m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.199m. TruncateEx(1));
Assert.AreEqual(-0.1m, -0.101m. TruncateEx(1));
Assert.AreEqual(0m, -0.099m. TruncateEx(1));
Assert.AreEqual(0m, -0.001m. TruncateEx(1));
Assert.AreEqual(1m, 1.99m. TruncateEx(0));
Assert.AreEqual(1m, 1.01m. TruncateEx(0));
Assert.AreEqual(-1m, -1.99m. TruncateEx(0));
Assert.AreEqual(-1m, -1.01m. TruncateEx(0));
}
En algunas condiciones, esto puede ser suficiente.
Tenía un valor decimal de SubCent = 0.0099999999999999999999999999M que tiende a formatear en | SubCent: 0.010000 | a través de string.Format("{0:N6}", SubCent );
y muchas otras opciones de formato.
Mi requisito no era redondear el valor de SubCent, pero tampoco registrar cada dígito.
Lo siguiente cumplió con mi requisito:
string.Format("SubCent:{0}|",
SubCent.ToString("N10", CultureInfo.InvariantCulture).Substring(0, 9));
Lo cual devuelve la cadena: | SubCent: 0.0099999 |
Para acomodar el valor que tiene una parte entera, lo siguiente es un comienzo.
tmpValFmt = 567890.0099999933999229999999M.ToString("0.0000000000000000000000000000");
decPt = tmpValFmt.LastIndexOf(".");
if (decPt < 0) decPt = 0;
valFmt4 = string.Format("{0}", tmpValFmt.Substring(0, decPt + 9));
Lo cual devuelve la cadena:
valFmt4 = "567890.00999999"
En realidad quieres 3.46 de 3.4679. Esta es solo la representación de los caracteres. Por lo tanto, no hay nada que ver con la función matemática. La función principal no está destinada a hacer este trabajo. Simplemente use el siguiente código.
Dim str1 As String
str1=""
str1 ="3.4679"
Dim substring As String = str1.Substring(0, 3)
'' Write the results to the screen.
Console.WriteLine("Substring: {0}", substring)
Or
Please use the following code.
Public function result(ByVal x1 As Double) As String
Dim i as Int32
i=0
Dim y as String
y = ""
For Each ch as Char In x1.ToString
If i>3 then
Exit For
Else
y + y +ch
End if
i=i+1
Next
return y
End Function
El código anterior puede modificarse para cualquier número Poner el siguiente código en un evento de clic de botón
Dim str As String
str= result(3.4679)
MsgBox("The number is " & str)
Método universal y rápido (sin Math.Pow()
/ multiplication) para System.Decimal
:
decimal Truncate(decimal d, byte decimals)
{
decimal r = Math.Round(d, decimals);
if (d > 0 && r > d)
{
return r - new decimal(1, 0, 0, false, decimals);
}
else if (d < 0 && r < d)
{
return r + new decimal(1, 0, 0, false, decimals);
}
return r;
}
Sería más útil tener una función completa para el uso en el mundo real de truncar un decimal en C #. Esto podría convertirse a un método de extensión decimal bastante fácil si quisiera:
public decimal TruncateDecimal(decimal value, int precision)
{
decimal step = (decimal)Math.Pow(10, precision);
decimal tmp = Math.Truncate(step * value);
return tmp / step;
}
Si necesita VB.NET intente esto:
Function TruncateDecimal(value As Decimal, precision As Integer) As Decimal
Dim stepper As Decimal = Math.Pow(10, precision)
Dim tmp As Decimal = Math.Truncate(stepper * value)
Return tmp / stepper
End Function
Entonces úsalo así:
decimal result = TruncateDecimal(0.275, 2);
o
Dim result As Decimal = TruncateDecimal(0.275, 2)
Si no se preocupa demasiado por el rendimiento y su resultado final puede ser una cadena, el siguiente enfoque será resistente a los problemas de precisión flotante:
string Truncate(double value, int precision)
{
if (precision < 0)
{
throw new ArgumentOutOfRangeException("Precision cannot be less than zero");
}
string result = value.ToString();
int dot = result.IndexOf(''.'');
if (dot < 0)
{
return result;
}
int newLength = dot + precision + 1;
if (newLength == dot + 1)
{
newLength--;
}
if (newLength > result.Length)
{
newLength = result.Length;
}
return result.Substring(0, newLength);
}
Un problema con los otros ejemplos es que multiplican el valor de entrada antes de dividirlo. Aquí hay un caso de borde que puede desbordar decimal multiplicando primero, un caso marginal, pero algo que he encontrado. Es más seguro tratar la parte fraccional por separado de la siguiente manera:
public static decimal TruncateDecimal(this decimal value, int decimalPlaces)
{
decimal integralValue = Math.Truncate(value);
decimal fraction = value - integralValue;
decimal factor = (decimal)Math.Pow(10, decimalPlaces);
decimal truncatedFraction = Math.Truncate(fraction * factor) / factor;
decimal result = integralValue + truncatedFraction;
return result;
}
Use el operador de módulo:
var fourPlaces = 0.5485M;
var twoPlaces = fourPlaces - (fourPlaces % 0.01M);
resultado: 0.54
que tal esto?
Function TruncateDecimal2(MyValue As Decimal) As Decimal
Try
Return Math.Truncate(100 * MyValue) / 100
Catch ex As Exception
Return Math.Round(MyValue, 2)
End Try
End Function
value = Math.Truncate(100 * value) / 100;
Tenga en cuenta que las fracciones como estas no se pueden representar con precisión en coma flotante.