截去小数点后两位,不要四舍五入

假设我的值是3.4679,而我想要3.46,那么我怎样才能不用四舍五入就把小数点后两位截断呢?

我试过以下三种方法,但都得到了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));
}

这个返回3.46,但似乎有些肮脏:

void Main()
{
Console.Write(Math.Round(3.46799999999 -.005 , 2));
}
230588 次浏览
value = Math.Truncate(100 * value) / 100;

注意,像这样的分数不能准确地用浮点数表示。

这样可以吗?

Console.Write(((int)(3.4679999999*100))/100.0);

((long)(3.4679 * 100)) / 100.0会给你想要的吗?

如果有一个完整的函数用于在 C # 中截断小数的实际应用,那将会更加有用。如果您愿意,这可以很容易地转换为 Decimal 扩展方法:

public decimal TruncateDecimal(decimal value, int precision)
{
decimal step = (decimal)Math.Pow(10, precision);
decimal tmp = Math.Truncate(step * value);
return tmp / step;
}

如果你需要 VB.NET,试试这个:

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

然后像这样使用它:

decimal result = TruncateDecimal(0.275, 2);

或者

Dim result As Decimal = TruncateDecimal(0.275, 2)

其他示例的一个问题是,它们将输入值 之前相乘除以它。这里有一个边界情况,你可以通过先乘以溢出小数,一个边界情况,但我遇到的东西。将小数部分分开处理比较安全,如下所示:

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

如果您不太担心性能问题,并且您的最终结果可能是一个字符串,那么下面的方法可以很好地解决浮动精度问题:

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

使用模运算符:

var fourPlaces = 0.5485M;
var twoPlaces = fourPlaces - (fourPlaces % 0.01M);

结果: 0.54

我将留下十进制数的解。

这里的一些小数解决方案很容易溢出(如果我们传递一个非常大的小数,并且该方法会尝试将其相乘)。

提姆劳埃德的解决方案是防止溢出,但它不是太快。

下面的解决方案大约快2倍,而且没有溢出问题:

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

下面是 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);
}

下面是一个扩展方法:

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

其实你想要3.46从3.4679。 这只是字符的表示,与数学函数无关。数学函数不是用来做这项工作的。 只需使用以下代码。

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

以上代码可以修改为任何数字 按钮单击事件中的代码

Dim str As String
str= result(3.4679)
MsgBox("The number is " & str)

这个怎么样?

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

除了上述的解决方案外,我们还有另一种方法可以实现。

    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

System.Decimal的通用快速方法(不含 Math.Pow()/乘法) :

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

在某些情况下,这可能就足够了。

我的十进制值是 SubCent = 0.009999999999999999999999999999999 M ,倾向于通过 string.Format("{0:N6}", SubCent );和许多其他格式选择格式化为 0.010000

我的要求是不要四舍五入 SubCent 值,但也不要记录每个数字。

以下内容符合我的要求:

string.Format("SubCent:{0}|",
SubCent.ToString("N10", CultureInfo.InvariantCulture).Substring(0, 9));

返回字符串: 0.0099999

为了适应具有整数部分的值,下面是一个开始。

tmpValFmt = 567890.0099999933999229999999M.ToString("0.0000000000000000000000000000");
decPt = tmpValFmt.LastIndexOf(".");
if (decPt < 0) decPt = 0;
valFmt4 = string.Format("{0}", tmpValFmt.Substring(0, decPt + 9));

返回字符串:

valFmt4 = "567890.00999999"

我使用这个函数来截断字符串变量中的小数后面的值

public static string TruncateFunction(string value)
{
if (string.IsNullOrEmpty(value)) return "";
else
{
string[] split = value.Split('.');
if (split.Length > 0)
{
string predecimal = split[0];
string postdecimal = split[1];
postdecimal = postdecimal.Length > 6 ? postdecimal.Substring(0, 6) : postdecimal;
return predecimal + "." + postdecimal;


}
else return value;
}
}

这是一个古老的问题,但是对于大数字,许多答案并不能很好地执行或者溢出。我认为 D · 涅斯捷罗夫的回答是最好的: 稳健、简单、迅速。我只是想补充一下我的看法。 我玩了 小数,也看了 源代码。从 public Decimal (int lo, int mid, int hi, bool isNegative, byte scale)构造函数文档

Decimal 数的二进制表示由1位组成 符号、96位整数和用于除以 整数,并指定其中的哪一部分是小数分数。 比例因子是隐式的数字10提高到一个指数 从0到28。

知道了这一点,我的第一个方法是创建另一个 decimal,它的刻度对应于我想要丢弃的小数,然后截断它,最后创建一个具有所需刻度的小数。

private const int ScaleMask = 0x00FF0000;
public static Decimal Truncate(decimal target, byte decimalPlaces)
{
var bits = Decimal.GetBits(target);
var scale = (byte)((bits[3] & (ScaleMask)) >> 16);


if (scale <= decimalPlaces)
return target;


var temporalDecimal = new Decimal(bits[0], bits[1], bits[2], target < 0, (byte)(scale - decimalPlaces));
temporalDecimal = Math.Truncate(temporalDecimal);


bits = Decimal.GetBits(temporalDecimal);
return new Decimal(bits[0], bits[1], bits[2], target < 0, decimalPlaces);
}

这个方法并不比 D. Nesterov 的方法快,而且更复杂,所以我多花了一点时间。我的猜测是,必须创建一个辅助 decimal和检索位两次使它变得更慢。在我的第二次尝试中,我自己操纵了由 Decimal. GetBits (Decimal d)方法返回的组件。这个想法是根据需要将组件除以10倍,并缩小规模。代码主要基于 Decimal.InternalRoundFromZero (ref Decimal d,int decalCount)方法

private const Int32 MaxInt32Scale = 9;
private const int ScaleMask = 0x00FF0000;
private const int SignMask = unchecked((int)0x80000000);
// Fast access for 10^n where n is 0-9
private static UInt32[] Powers10 = new UInt32[] {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};


public static Decimal Truncate(decimal target, byte decimalPlaces)
{
var bits = Decimal.GetBits(target);
int lo = bits[0];
int mid = bits[1];
int hi = bits[2];
int flags = bits[3];


var scale = (byte)((flags & (ScaleMask)) >> 16);
int scaleDifference = scale - decimalPlaces;
if (scaleDifference <= 0)
return target;


// Divide the value by 10^scaleDifference
UInt32 lastDivisor;
do
{
Int32 diffChunk = (scaleDifference > MaxInt32Scale) ? MaxInt32Scale : scaleDifference;
lastDivisor = Powers10[diffChunk];
InternalDivRemUInt32(ref lo, ref mid, ref hi, lastDivisor);
scaleDifference -= diffChunk;
} while (scaleDifference > 0);




return new Decimal(lo, mid, hi, (flags & SignMask)!=0, decimalPlaces);
}
private static UInt32 InternalDivRemUInt32(ref int lo, ref int mid, ref int hi, UInt32 divisor)
{
UInt32 remainder = 0;
UInt64 n;
if (hi != 0)
{
n = ((UInt32)hi);
hi = (Int32)((UInt32)(n / divisor));
remainder = (UInt32)(n % divisor);
}
if (mid != 0 || remainder != 0)
{
n = ((UInt64)remainder << 32) | (UInt32)mid;
mid = (Int32)((UInt32)(n / divisor));
remainder = (UInt32)(n % divisor);
}
if (lo != 0 || remainder != 0)
{
n = ((UInt64)remainder << 32) | (UInt32)lo;
lo = (Int32)((UInt32)(n / divisor));
remainder = (UInt32)(n % divisor);
}
return remainder;
}

我没有进行过严格的性能测试,但是在 MacOS Sierra 10.12.6,3,06GHz Intel Core i3处理器上进行了测试。NetCore 2.1这种方法似乎比 D。 Nesterov 的方法快得多(我不会给出数字,因为我已经提到过,我的测试并不严格)。这取决于实现它的人来评估增加的代码复杂性是否会带来性能收益。

我就是这么做的:

        c1 = a1 - b1;
d1 = Math.Ceiling(c1 * 100) / 100;

减去两个输入的数字而不四舍五入小数。 因为其他的方法对我不起作用。 不知道对别人是否有用,我只是想分享一下:) 希望对于那些正在寻找类似问题的解决方案的人有用。谢谢

PS: 我是一个初学者,所以请随意指出这方面的东西 如果你真的在和钱打交道,这是件好事,因为钱,对吧?它只有两个小数位,四舍五入是一个没有。

怎么了

var i = Math.Truncate(number);

var r = i + Math.Truncate((number - i) * 100) / 100;
        public static void ReminderDigints(decimal? number, out decimal? Value,  out decimal? Reminder)
{
Reminder = null;
Value = null;
if (number.HasValue)
{
Value = Math.Floor(number.Value);
Reminder = (number - Math.Truncate(number.Value));
}
}






decimal? number= 50.55m;
ReminderDigints(number, out decimal? Value, out decimal? Reminder);
public static decimal TruncateDecimalPlaces(this decimal value, int precision)
{
try
{
step = (decimal)Math.Pow(10, precision);
decimal tmp = Math.Truncate(step * value);
return tmp / step;
}
catch (OverflowException)
{
step = (decimal)Math.Pow(10, -1 * precision);
return value - (value % step);
}
}

我最喜欢的是

var myvalue = 54.301012345;
var valueiwant = myvalue.toString("0.00");
//result => "54.30"


//additional
var valueiwant2 = myvalue.toString("0.##");
//result => "54.3" // without zero

进去。NET Core 3.0及以后的 Math.RoundDecimal.Round可以通过新的 中点四舍五入截断数字。对于正数,MidpointRounding.ToNegativeInfinity具有相同的效果,而对于负数,相当于 MidpointRounding.ToPositiveInfinity

这些台词:

Console.WriteLine(Math.Round(3.4679, 2,MidpointRounding.ToZero));
Console.WriteLine(Math.Round(3.9999, 2,MidpointRounding.ToZero));
Console.WriteLine(Math.Round(-3.4679, 2,MidpointRounding.ToZero));
Console.WriteLine(Math.Round(-3.9999, 2,MidpointRounding.ToZero));

产品:

3.46
3.99
-3.46
-3.99

函数来截断任何十进制数而不四舍五入

public static double round(double d, byte p)
{
return Math.Truncate(d * Math.Pow(10, p)) / Math.Pow(10, p);
}