Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#检查小数点是否超过3位?_C#_Decimal - Fatal编程技术网

C#检查小数点是否超过3位?

C#检查小数点是否超过3位?,c#,decimal,C#,Decimal,我有一种无法改变的情况:一个数据库表(表a)接受6位小数,而另一个表(表B)中的相关列只有3位小数 我需要从A复制到B,但如果A的小数点超过3位,额外的数据将丢失。我无法更改表定义,但可以添加一个变通方法。所以我想知道如何检查小数点是否超过3位 乙二醇 我想知道表A中的数量*单位是否超过3位小数(第1行将失败,第2行将通过): 我该如何实现CountDecimalPlaces(decimalvalue){}函数?可能有一种更优雅的方法来实现这一点,但我会立即尝试 bool CountDe

我有一种无法改变的情况:一个数据库表(表a)接受6位小数,而另一个表(表B)中的相关列只有3位小数

我需要从A复制到B,但如果A的小数点超过3位,额外的数据将丢失。我无法更改表定义,但可以添加一个变通方法。所以我想知道如何检查小数点是否超过3位

乙二醇

我想知道表A中的数量*单位是否超过3位小数(第1行将失败,第2行将通过):


我该如何实现CountDecimalPlaces(decimalvalue){}函数?

可能有一种更优雅的方法来实现这一点,但我会立即尝试

    bool CountDecimalPlaces(decimal input)
    {
        return input*1000.0 == (int) (input*1000);
    }
  • a=乘以1000
  • b=截断a
  • 如果(b!=a),则会损失额外的精度

  • 你能把它转换成一个字符串,然后只做一个len函数吗?或者这不包括你的情况吗

    跟进问题:
    300.4行吗?

    基本知识是要知道如何测试是否有小数点,这是通过比较数值与其舍入值来完成的

    double number;
    bool hasDecimals = number == (int) number;
    
    然后,要计算小数点后3位,只需对数字乘以1000进行相同的运算:

    bool hasMoreThan3decimals = number*1000 != (int) (number * 1000)
    

    这适用于小数点后3位,并可适用于一般解决方案:

    static bool LessThan3DecimalPlaces(decimal dec)
    {
        decimal value = dec * 1000;
        return value == Math.Floor(value);
    }
    static void Test()
    {
        Console.WriteLine(LessThan3DecimalPlaces(1m * 0.00025m));
        Console.WriteLine(LessThan3DecimalPlaces(4000m * 0.00025m));
    }
    
    对于真正的通用解决方案,您需要“解构”十进制值的各个部分-查看以获取更多信息

    更新:这是一个通用解决方案的简单实现,适用于整数部分小于long.MaxValue的所有小数(对于真正通用的函数,您需要类似“大整数”的东西)

    静态十进制计数小数位数(十进制小数)
    {
    Console.Write(“{0}:”,dec);
    int[]位=十进制.GetBits(十进制);
    ulong lowInt=(uint)位[0];
    ulong midInt=(uint)位[1];
    整数指数=(位[3]&0x00FF0000)>>16;
    int结果=指数;
    ulong lowDecimal=lowInt |(中间值0&&(lowDecimal%10)=0)
    {
    结果--;
    低十进制/=10;
    }
    返回结果;
    }
    静态void Foo()
    {
    控制台写入线(计数小数位数(1.6m));
    控制台写入线(CountDecimalPlaces(1.600m));
    Console.WriteLine(CountDecimalPlaces(decimal.MaxValue));
    控制台写入线(十进制位置(1m*0.00025m));
    控制台写入线(计数小数位数(4000m*0.00025m));
    }
    
    目前提出的所有解决方案都不可扩展。。。如果您永远不会检查3以外的值,那么这很好,但我更喜欢这样,因为如果需求更改代码以处理它,那么代码已经编写好了。而且这个解决方案不会溢出

    int GetDecimalCount(decimal val)
    {
        if(val == val*10)
        {
            return int.MaxValue; // no decimal.Epsilon I don't use this type enough to know why... this will work
        }
    
        int decimalCount = 0;
        while(val != Math.Floor(val))
        {
            val = (val - Math.Floor(val)) * 10;
            decimalCount++;
        }
        return decimalCount;
    }       
    

    您可以将四舍五入到小数点后3位的数字值与原始值进行比较

    if (Decimal.Round(valueDecimal, 3) != valueDecimal)
    {
       //Too many decimals
    }
    

    carlosfigueira解决方案将需要检查0,否则“而((低十进制%10)==0)”在使用dec=0调用时将产生一个无限循环

    static decimal CountDecimalPlaces(decimal dec)
        {
            if (dec == 0)
                return 0;
            int[] bits = Decimal.GetBits(dec);
            int exponent = bits[3] >> 16;
            int result = exponent;
            long lowDecimal = bits[0] | (bits[1] >> 8);
            while ((lowDecimal % 10) == 0)
            {
                result--;
                lowDecimal /= 10;
            }
            return result;
        }
    
        Assert.AreEqual(0, DecimalHelper.CountDecimalPlaces(0m));      
        Assert.AreEqual(1, DecimalHelper.CountDecimalPlaces(0.5m));
        Assert.AreEqual(2, DecimalHelper.CountDecimalPlaces(10.51m));
        Assert.AreEqual(13, DecimalHelper.CountDecimalPlaces(10.5123456978563m));
    

    将一个小数点后3位的数字乘以10的3次方,将得到一个没有小数点的数字。当模数
    %1==0
    时,它是一个整数。所以我想出了这个

    bool hasMoreThanNDecimals(decimal d, int n)
    {
        return !(d * (decimal)Math.Pow(10, n) % 1 == 0);
    }
    

    n
    小于(不等于)小数位数时,返回true

    这是一个非常简单的单行代码,用于获取十进制中的小数计数:

    decimal myDecimal = 1.000000021300010000001m;
    byte decimals = (byte)((Decimal.GetBits(myDecimal)[3] >> 16) & 0x7F);
    

    基于@RodH257解决方案的另一个选项,但作为扩展方法进行了修改:

    public static bool HasThisManyDecimalPlacesOrLess(this decimal value, int noDecimalPlaces)
    {
        return (Decimal.Round(value, noDecimalPlaces) == value);
    }
    
    您可以将其称为:

    If !(tableA.Qty * tableA.Unit).HasThisManyDecimalPlacesOrLess(3)) return;
    
    以下是我的版本:

    public static int CountDecimalPlaces(decimal dec)
    {
        var a = Math.Abs(dec);
        var x = a;
        var count = 1;
        while (x % 1 != 0)
        {
            x = a * new decimal(Math.Pow(10, count++));
        }
    
        var result = count - 1;
    
        return result;
    }
    
    我首先尝试了
    @carlosfigueira/@Henrik Stenbæk
    ,但他们的版本不适用于
    324000.00m

    测试:


    +1-我认为LessThan3DecimalPlaces应该是lessthanQualTo3decimalplaces:)CountDecimalPlaces如果使用dec==0@LuisLavieri/HenrikStenbæk好渔获量;我已经更新了这个函数来解释这些情况。很容易阅读,也很容易更改小数点的位置。一段漂亮优雅的代码,谢谢!这正是我在阅读了公认的解决方案后要添加的答案,但您已经有了!你能给你的代码添加一些解释吗?我不关心额外的零,所以decWork.ToString.Trim(“0”)会删除它们,.50变成.5 strecabs.substringstrecabs.Substring(strecabs.IndexOf(“.”).Length-1给出从小数点开始的字符串长度,由于该点已包含在内,因此我减去1。除非指定了区域性信息,否则不会适用于所有语言,因此请小心这应该是答案,您只是迟到了。干得好。出于好奇,为什么是(byte)而不是(int)或其他什么?我会回答同样的问题,扩展方法肯定是最有用的解决方案。我将该方法命名为HasMaxDecimalPlaces(),只是为了将“this many or less”简化为“max”
    decimal myDecimal = 1.000000021300010000001m;
    byte decimals = (byte)((Decimal.GetBits(myDecimal)[3] >> 16) & 0x7F);
    
    public static bool HasThisManyDecimalPlacesOrLess(this decimal value, int noDecimalPlaces)
    {
        return (Decimal.Round(value, noDecimalPlaces) == value);
    }
    
    If !(tableA.Qty * tableA.Unit).HasThisManyDecimalPlacesOrLess(3)) return;
    
    public static int CountDecimalPlaces(decimal dec)
    {
        var a = Math.Abs(dec);
        var x = a;
        var count = 1;
        while (x % 1 != 0)
        {
            x = a * new decimal(Math.Pow(10, count++));
        }
    
        var result = count - 1;
    
        return result;
    }
    
    Console.WriteLine(CountDecimalPlaces(0m)); //0
    Console.WriteLine(CountDecimalPlaces(0.5m)); //1
    Console.WriteLine(CountDecimalPlaces(10.51m)); //2
    Console.WriteLine(CountDecimalPlaces(10.5123456978563m)); //13
    Console.WriteLine(CountDecimalPlaces(324000.0001m)); //4
    Console.WriteLine(CountDecimalPlaces(324000.0000m)); //0