1.4726保留整数 保留一位小数 保留两位小数 保留三位小数各是多少
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.4726保留整数 保留一位小数 保留两位小数 保留三位小数各是多少相关的知识,希望对你有一定的参考价值。
保留小数位的方法有3种,常用的和默认使用的保留有效数字位数的方法是四舍五入法,在一些特殊地方也会用到向下保留和向上保留有效数字,分别如下:
1、四舍五入法
保留整数:1
保留1位小数:1.5
保留2位小数:1.47
保留3位小数:1.473
2、向上取整保留有效数字,即不管是多少,都进一位
保留整数:2
保留1位小数:1.5
保留2位小数:1.48
保留3位小数:1.473
3、向下取整保留有效数字,即不管多少,都舍弃。
保留整数:1
保留1位小数:1.3
保留2位小数:1.47
保留3位小数:1.472
扩展资料:
舍入规则
1、当保留n位有效数字,若第n+1位数字≤4就舍掉。
2、当保留n位有效数字,若第n+1位数字≥6时,则第n位数字进1。
3、当保留n位有效数字,若第n+1位数字=5且后面数字为0时 ,则第n位数字若为偶数时就舍掉后面的数字,若第n位数字为奇数时加1;若第n+1位数字=5且后面还有不为0的任何数字时,无论第n位数字是奇或是偶都加1。
参考资料来源:百度百科-有效数字
参考技术A 用四舍五入法,1.4726保留整数是1。用四舍五入法,1.4726保留一位小数是1.5。
用四舍五入法,1.4726保留两位小数是1.47。
用四舍五入法,1.4726保留三位小数是1.473。 参考技术B 4、9762保留整数是(),保留一位小数是(),保留两位小数是()。 参考技术C 1/1.5/1.47/1.473 参考技术D 1.5 1.47 1.473
截断两位小数,不四舍五入
【中文标题】截断两位小数,不四舍五入【英文标题】:Truncate Two decimal places without rounding 【发布时间】:2011-03-09 18:57:39 【问题描述】:假设我有一个值 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));
【问题讨论】:
【参考方案1】:value = Math.Truncate(100 * value) / 100;
请注意,此类分数无法用浮点数准确表示。
【讨论】:
使用小数作为你的值,这个答案会起作用。它不可能总是在任何浮点表示中工作。 这让我想知道是否应该可以在浮点文字中指定舍入方向。嗯。 必须有 some 方法告诉程序员,假设一个数字可以存储超过 308 位数字的计算是严重不合适的。 Double 只能存储 15 个。溢出是这里非常重要的一个特性,溢出相当严重。 对不起,我以为“值”是十进制的。【参考方案2】:这对你有用吗?
Console.Write(((int)(3.4679999999*100))/100.0);
【讨论】:
【参考方案3】:((long)(3.4679 * 100)) / 100.0
会给你想要的吗?
【讨论】:
【参考方案4】:在 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)
【讨论】:
这将溢出大量数字。 要添加到夜间编码器,您在函数中使用 Int32 作为中介的事实将导致溢出。如果您确实必须将其转换为整数,则应使用 Int64。问题是为什么你会想要产生额外的开销,因为 Truncate 无论如何都会返回 Decimal 积分。只需执行以下操作:小数步长 = (decimal)Math.Pow(10,precision); return Math.Truncate(step * value) / step; 我将演员阵容改为整数。为了更好地阅读和理解函数的工作原理,我将它们分开了几行。【参考方案5】:其他示例的一个问题是它们将输入值相乘然后除以它。这里有一个边缘情况,你可以通过先乘以溢出小数,这是一个边缘情况,但我遇到了一些事情。小数部分分开处理比较安全:
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;
【讨论】:
我知道这是旧的,但我注意到并对此提出了问题。您在这里拥有的因素是一个 int ,因此如果您截断到大量小数位(例如 25 位),它将导致最终结果出现精度错误。我通过将因子类型更改为十进制来修复它。 @TheKingDave:可能这无关紧要,但由于因子不能有小数,应该更好地建模它吧? @SoMoS 对我来说,十进制效果更好,因为它为我提供了最高的因子存储值。它仍然有一个限制,但对于我的应用程序来说已经足够大了。另一方面,Long 无法为我的应用程序存储足够大的数字。例如,如果您使用 long 执行 Truncate(25),那么会有一些不准确。 根据@TheKingDave 的建议进行了更新,允许截断到更多的位置,谢谢。【参考方案6】:如果您不太担心性能并且您的最终结果可以是字符串,那么以下方法将能够应对浮动精度问题:
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);
【讨论】:
其实是硬编码'.'不是个好主意,最好使用 System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator[0]【参考方案7】:使用取模运算符:
var fourPlaces = 0.5485M;
var twoPlaces = fourPlaces - (fourPlaces % 0.01M);
结果:0.54
【讨论】:
我不明白(阅读:没有花时间去验证)所有其他花哨的解决方案,这正是我正在寻找的。谢谢! 在 .Net Fiddle clicky 上运行此程序会产生0.5400
... 下面的 answer by D. Nesterov 会产生预期的 0.54
。
您确实意识到,@ttugates,0.54 和 0.5400 是完全相同的值,对吧?除非/直到需要格式化以进行显示,否则后面有多少个零并不重要——在这种情况下,如果格式化正确,结果将是相同的:$"0.54m:C"
产生 "$0.54"
,是的,$"0.5400m:C"
产生 @987654329 @.
这是一个有点懒惰的答案,应该更新它以实际显示您将值返回到小数点后两位,正如指出的这段代码不这样做。如果我们正在考虑完整性和迂腐,我就是这样,这只是部分答案,它确实回答了删除舍入组件的问题,但同样,在技术上并不完整。
我喜欢这个答案。简单但效果很好【参考方案8】:
我将保留十进制数的解决方案。
这里的一些小数解很容易溢出(如果我们传递一个非常大的十进制数并且方法会尝试将它相乘)。
Tim Lloyd 的解决方案可以防止溢出,但速度不会太快。
以下解决方案大约快 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));
【讨论】:
我不喜欢给它加上“Ex”的后缀。 C# 支持重载,您的Truncate
方法将与.net 原生方法组合在一起,为用户提供无缝体验。
您的算法产生了一些不正确的结果。默认的 MidpointRounding 模式是 Banker's Rounding,它将 0.5 舍入到最接近的偶数值。 Assert.AreEqual(1.1m, 1.12m.TruncateEx(1));
因此失败。如果您在 Math.Round 调用中指定“正常”舍入 (AwayFromZero),则 Assert.AreEqual(0m, 0m.TruncateEx(1));
失败
此解决方案唯一可行的方法是使用 MidpointRounding.AwayFromZero
并专门使用代码来处理值 0。
Jon 是正确的:0m.TruncateEx(0) 会导致 -1,除非明确处理 0。同样 -11m.TruncateEx(0) 的结果是 -10,除非在 Math.Round 中使用 MidpointRounding.AwayFromZero。不过,这些修改似乎可以很好地工作。
即使更改了 AwayFromZero 并显式处理 0, -9999999999999999999999999999m.TruncateEx(0) 会导致 -9999999999999999999999999998,因此在某些情况下它仍然是错误的。【参考方案9】:
这是我对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);
【讨论】:
【参考方案10】:这是一个扩展方法:
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
【讨论】:
【参考方案11】:实际上你想要 3.46 from 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)
【讨论】:
【参考方案12】:这个呢?
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
【讨论】:
【参考方案13】:除了以上解决方案,我们还有另一种方式可以实现。
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
【讨论】:
【参考方案14】: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;
【讨论】:
我通过其他答案中提到的所有测试运行了这个,它运行良好。很惊讶它没有更多的赞成票。值得注意的是小数只能在 0 到 28 之间(对大多数人来说可能没问题)。 我同意这一点。这是最好的答案。 +1 很好的答案,这就是我所说的“跳出框框思考” 好答案。这也适用于双精度数据类型,如果我能够硬编码“new decimal(1, 0, 0, false, decimals)”的值;) 我该如何调用这个方法? var truncated = Truncate(decimalNumber, (byte)decimalPlaces);其中decimalNumber 是decimal 类型,decimalPlaces 是int 类型。这是正确的吗?【参考方案15】:在某些情况下,这可能就足够了。
我有一个十进制值
SubCent = 0.0099999999999999999999999999M,倾向于通过string.Format("0:N6", SubCent );
和许多其他格式选择格式化为 |SubCent:0.010000|。
我的要求不是对 SubCent 值进行四舍五入,也不是记录每个数字。
以下满足我的要求:
string.Format("SubCent:0|",
SubCent.ToString("N10", CultureInfo.InvariantCulture).Substring(0, 9));
返回字符串:|SubCent: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"
【讨论】:
【参考方案16】:我正在使用这个函数来截断字符串变量中小数点后的值
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;
【讨论】:
虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。【参考方案17】:这是一个老问题,但许多 anwsers 表现不佳或因大数字而溢出。我认为 D. Nesterov 的答案是最好的:健壮、简单和快速。我只想加两分钱。
我玩过decimals,还查看了source code。来自public Decimal (int lo, int mid, int hi, bool isNegative, byte scale)
constructor documentation。
十进制数的二进制表示由一个 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) method 返回的组件。这个想法是根据需要将组件除以 10 倍并减小规模。该代码(大量)基于Decimal.InternalRoundFromZero(ref Decimal d, int decimalCount) method。
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,06 GHz Intel Core i3 处理器和目标 .NetCore 2.1 上,这种方法似乎比 D. Nesterov 的快得多(我不会给出数字,因为正如我所提到的,我的测试并不严格)。由谁来实现它来评估性能提升是否会因增加的代码复杂性而得到回报。
【讨论】:
由于所有的想法和努力,我不得不投票。您将 Nesterov 设为基准并继续前进 - 脱帽致敬。【参考方案18】:这就是我所做的:
c1 = a1 - b1;
d1 = Math.Ceiling(c1 * 100) / 100;
减去两个输入的数字,不四舍五入小数。 因为其他解决方案对我不起作用。 不知道它是否适用于其他人,我只是想分享这个:) 希望它适用于那些正在寻找与我类似的问题的解决方案的人。谢谢
PS:我是一个初学者,所以请随时指出这一点。 :D 如果您实际上是在处理金钱,这很好,因为美分对吗?它只有 2 位小数,四舍五入是不行的。
【讨论】:
【参考方案19】:怎么样
var i = Math.Truncate(number);
var r = i + Math.Truncate((number - i) * 100) / 100;
【讨论】:
【参考方案20】: 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);
【讨论】:
【参考方案21】: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);
【讨论】:
如果“精度”为 2,catch 块中的计算会在小数点后两位产生额外的零【参考方案22】:我最喜欢的是
var myvalue = 54.301012345;
var valueiwant = myvalue.toString("0.00");
//result => "54.30"
//additional
var valueiwant2 = myvalue.toString("0.##");
//result => "54.3" // without zero
【讨论】:
【参考方案23】:在 .NET Core 3.0 及更高版本中,Math.Round
和 Decimal.Round
可以通过新的 MidpointRounding.ToZero 截断数字。对于正数,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
【讨论】:
根据docs,没有必要用ToZero
区分正负:2.8和2.1都用它截断为2,对于-2.8和-2.1,结果是-2 .
重要提示:您确实需要 .NET 5.0,但对于 4.0 版,您只能使用 AwayFromZero
和 ToEven
。
@Neph 这从 .NET Core 3 开始可用。从来没有 .NET Core 4。.NET 5 是 .NET Core 5。旧的 .NET Framework 停止了在 4.8
我说的是“常规”.NET 5.0 版本(不确定它是如何连接到“Core”的,...)。我之所以提到这一点,是因为 Unity 2021 仅支持“.NET Standard 2.0”和“.NET 4.x”C# 和 ToZero
,甚至不幸的是其他两个都不支持。
@Neph 没有“常规”。 .NET 5 是 .NET Core 5 的当前版本。出于营销目的而更改了名称。它包括几乎所有将要迁移到 .NET Core 的 .NET Old API,因此决定通过...统一名称来“统一”平台【参考方案24】:
截断任何十进制数而不四舍五入的函数
public static double round(double d, byte p)
return Math.Truncate(d * Math.Pow(10, p)) / Math.Pow(10, p);
【讨论】:
以上是关于1.4726保留整数 保留一位小数 保留两位小数 保留三位小数各是多少的主要内容,如果未能解决你的问题,请参考以下文章