我知道.NET有一个内置但是它是一个外部调用。谁知道为什么?
但实际的问题是如何从头开始实现截断,用户可以指定要保留多少位数?将数字乘以100表示然后再除以相同的数量?或者是否有更好的实施?
类似的东西:
Truncate(12.3456789, 3);
// returns 12.345
答案 0 :(得分:2)
您可能希望查看IEEE浮点整数。
然后,您可以使用unsafe
代码修改数字,例如:
unsafe
{
double* pValue = &value;
var asLong = *(long*)pValue;
do whatever you want with asLong, e.g. bit-masking it, etc.;
}
关于'为什么':我不知道,虽然Shared Source CLI可能提供线索。我的猜测可能是因为性能优化。
答案 1 :(得分:2)
经典方式:
var x = 1.2345678;
var tr = 4;
var truncated = (int) (x * Math.Pow(10, tr)) / Math.Pow(10, tr);
会给出1.2345;
答案 2 :(得分:1)
我将如何做到这一点。在C ++中,我认为在C#中,您可以通过将其转换为整数类型来获取浮点数的整数部分。
double Truncate (double num, int dig)
{
if (dig > 15) dig = 15; // Don't overflow
long p = Math.Pow (10, dig);
// Save the integer part, so that we don't overflow
long integer_part = (long)num;
// Fractional part * 10^dig
double frac = (num - Convert.ToDouble(integer_part)) * p;
long frac_trunc = (long)frac;
// Final result
double result = Convert.ToDouble(integer_part) + (Convert.ToDouble(frac_trunc) / p);
return result;
}
将数字乘以100表示然后将其除以相同值 金额够吗?
这应该可行,但要小心,因为大数字或大量数字,你很容易溢出,它会给你奇怪的结果。
答案 3 :(得分:0)
var result = Math.Round(12.3456789, 3);
答案 4 :(得分:-1)
您认为Truncate应保留decmial值的原因尚不清楚。
.NET中的默认方法由以下语句描述:
d的组成部分;也就是说,任何之后剩下的数字 小数位已被丢弃。
看起来你想要使用的是格式化double / decmial值的输出字符串和/或使用Math.Round(double,int)函数。
你可以使用:
double num = 2.22939393; num = Convert.ToDouble(num.ToString("#0.000"));
从其中一个重复的问题:
public static decimal TruncateToDecimalPlace(this decimal numberToTruncate, int decimalPlaces)
{
decimal power = (decimal)(Math.Pow(10.0, (double)decimalPlaces));
return Math.Truncate((power * numberToTruncate)) / power;
}
我知道这仍然使用Truncate
方法。我之前只提供了此代码,因为您需要Truncate
方法来保留数字的decmial值,而默认的内置Truncate
方法则不会。
你总是可以使用它:
Math.Round不会从我能说出的内容中调用SplitFractionDouble
private static unsafe double InternalRound(double value, int digits, MidpointRounding mode) {
if (Abs(value) < doubleRoundLimit) {
Double power10 = roundPower10Double[digits];
value *= power10;
if (mode == MidpointRounding.AwayFromZero) {
double fraction = SplitFractionDouble(&value);
if (Abs(fraction) >= 0.5d) {
value += Sign(fraction);
}
}
else {
// On X86 this can be inlined to just a few instructions
value = Round(value);
}
value /= power10;
}
return value;
}
public static double Round(double value, int digits)
{
if ((digits < 0) || (digits > maxRoundingDigits))
throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
return InternalRound(value, digits, MidpointRounding.ToEven);
}
public static double Round(double value, MidpointRounding mode) {
return Round(value, 0, mode);
}
public static double Round(double value, int digits, MidpointRounding mode) {
if ((digits < 0) || (digits > maxRoundingDigits))
throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode");
}
return InternalRound(value, digits, mode);
}
public static Decimal Round(Decimal d) {
return Decimal.Round(d,0);
}
public static Decimal Round(Decimal d, int decimals) {
return Decimal.Round(d,decimals);
}
public static Decimal Round(Decimal d, MidpointRounding mode) {
return Decimal.Round(d, 0, mode);
}
public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) {
return Decimal.Round(d, decimals, mode);
}
public static Decimal Floor(Decimal d){ 返回Decimal.Floor(d); }
[MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern double Floor(double d);