How to get Smallest and Nearest Number to Zero using C#?
For example the smallest and nearest DECIMAL (DOUBLE) number to zero maybe is 0.000009 on one PC and 0.0000000000000000001 on another.
I mean The Most Possible result by 1/THE_MOST_LONG_INTEGER.
How to get it?
I guess you mean to calculate your Machine Epsilon ( http://en.wikipedia.org/wiki/Machine_epsilon ).
Which can be calculated in several ways, as example:
double machineEpsilon = 1.0d;
do {
machineEpsilon= machineEpsilon/ 2.0d;
}
while ((double)(1.0 + machineEpsilon) != 1.0);
I know it's an old question, but here's another possible method, trying to avoid iterations.
Based on the floating point format, you can just generate the smallest fraction artificially.
In C#, being sizeof(double)=64:
FOR NORMAL NUMBERS
public double GetMinNormalFraction()
{
double inf =double.PositiveInfinity ;
unsafe
{
ulong Inf_UL = *((ulong*)&inf);
ulong minFraction_UL = (Inf_UL ^ (Inf_UL << 1)) ^ ((1ul << 63) + 1ul);
return *((double*)&minFraction_UL); //2.2250738585072019E-308 in my computer
}
}
FOR SUBNORMAL/DENORMAL NUMBERS
public double GetMinDenormalFraction()
{
unsafe
{
ulong unit = 1ul;
return *((double*)&unit); //4.94065645841247E-324 in my computer
}
}
You can check if these are the smallest values using them as start point in machine-epsilon algorithm previously proposed by Saverio Terracciano (remembering to change to while ( machineEpsilon > 0.0); for denormal fractions)
EDIT
For the sake of completion but already out of the question, in case of needing the smallest fraction that can be added to a number, not just zero, the general method would be something like:
public double GetMinFractionCloseTo(double number)
{
//check if number is a denormal/subnormal number
if (double.IsNaN(number) || double.IsInfinity(number))
return 0.0; // or throw Exception,etc
unsafe
{
double inf = double.PositiveInfinity;
ulong Inf_UL = *((ulong*)&inf);
ulong Number_UL = *((ulong*)&number);
bool isDenormal = (Inf_UL & Number_UL) == 0;
if (isDenormal)
{
//MinFraction is always the same with denormals
ulong unit = 1ul;
return *((double*)&unit);
}
else //Normal number
{
//Detect if it's the last normal number close to zero
//(This can be skipped most of the times as it is very unlikely)
long maxLongValue = long.MaxValue;
ulong ExcludeSign= *((ulong*)&(maxLongValue));
ulong minFract_UL = (Inf_UL ^ (Inf_UL << 1)) | 1ul;
bool isLimitToDenormal = ((minFract_UL ^ Number_UL) & ExcludeSign) == 0;
if (isLimitToDenormal)
{
//MinFraction is always the same with denormals
ulong unit = 1ul;
return *((double*)&unit);
}
else
{
ulong ClosestValue_UL = Number_UL ^ 1ul;
double ClosestValue = *((double*)&(ClosestValue_UL));
return Math.Abs(number - ClosestValue);
}
}
}
}
Related
I have encountered this weird behaviour, which is probably best described by a small example:
Random R = new Random();
for (int i = 0; i < 10_000; i++)
{
double d = R.NextDouble() * uint.MaxValue;
}
Now, the last digit of d before the decimal mark is always even, i.e. int r = (int) (d % 10) is always 0, 2, 4, 6, or 8. There are odd digits on either side, though.
I suspected that multiplying with uint.MaxValue (2^32 - 1) could force some rounding error in the last digits, but since double has more than 50 bits of precision, this should beat uint with about 20 bits to spare after the separator. This behaviour also occurs if I explicitly store uint.MaxValue as a double before the multiplication and use that instead.
Can someone shed any light on this?
This is a deficiency in the .Net Random class.
If you inspect the source code you will see the following comment in the implementation of the private method GetSampleForLargeRange():
// The distribution of double value returned by Sample
// is not distributed well enough for a large range.
// If we use Sample for a range [Int32.MinValue..Int32.MaxValue)
// We will end up getting even numbers only.
This is used in the implementation of Next():
public virtual int Next(int minValue, int maxValue) {
if (minValue>maxValue) {
throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
}
Contract.EndContractBlock();
long range = (long)maxValue-minValue;
if( range <= (long)Int32.MaxValue) {
return ((int)(Sample() * range) + minValue);
}
else {
return (int)((long)(GetSampleForLargeRange() * range) + minValue);
}
}
But it is NOT used for the values returned from NextDouble() (which just returns the value returned from Sample().
So the answer is that NextDouble() is not well-distributed.
You can use RNGCryptoServiceProvider to generate better random numbers, but it's a bit of a fiddle to create the double. From this answer:
static void Main()
{
var R = new RNGCryptoServiceProvider();
var bytes = new Byte[8];
for (int i = 0; i < 10_000; i++)
{
R.GetBytes(bytes);
var ul = BitConverter.ToUInt64(bytes, 0) / (1 << 11);
var d = ul / (double)(1UL << 53);
d *= uint.MaxValue;
Console.WriteLine(d);
}
}
I want to calculate the slope of a line.
public sealed class Point
{
public System.Numerics.BigInteger x = 0;
public System.Numerics.BigInteger y = 0;
public double CalculateSlope (Point point)
{
return ((point.Y - this.Y) / (point.X - this.X));
}
}
I know that BigInteger has a DivRem function that returns the division result plus the remainder but am not sure how to apply it to get a double. The numbers I'm dealing with are far far beyond the range of Int64.MaxValue so the remainder itself could be out of range to calculate by conventional division.
EDIT:
Not sure if it helps but I'm dealing with only positive integers (>=1).
IMPORTANT: I only need a few decimal points of precision (5 should be good enough for my purpose).
Get BigRational from Codeplex. Its part of Microsoft's Base Class Library, so it's a work-in-progress for .Net. Once you have that, then do something like:
System.Numerics.BigInteger x = GetDividend() ;
System.Numerics.BigInteger y = GetDivisor() ;
BigRational r = new BigRational( x , y ) ;
double value = (double) r ;
Dealing with the inevitable overflow/underflow/loss of precision is, of course, another problem.
Since you can't drop the BigRational library into your code, evidently, the other approach would be to get out the right algorithms book and roll your own...
The easy way, of course, of "rolling one's own" here, since a rational number is represented as the ratio (division) of two integers, is to grab the explicit conversion to double operator from the BigRational class and tweak it to suit. It took me about 15 minutes.
About the only significant modification I made is in how the sign of the result is set when the result is positive or negative zero/infinity. While I was at it, I converted it to a BigInteger extension method for you:
public static class BigIntExtensions
{
public static double DivideAndReturnDouble( this BigInteger x , BigInteger y )
{
// The Double value type represents a double-precision 64-bit number with
// values ranging from -1.79769313486232e308 to +1.79769313486232e308
// values that do not fit into this range are returned as +/-Infinity
if (SafeCastToDouble(x) && SafeCastToDouble(y))
{
return (Double) x / (Double) y;
}
// kick it old-school and figure out the sign of the result
bool isNegativeResult = ( ( x.Sign < 0 && y.Sign > 0 ) || ( x.Sign > 0 && y.Sign < 0 ) ) ;
// scale the numerator to preseve the fraction part through the integer division
BigInteger denormalized = (x * s_bnDoublePrecision) / y ;
if ( denormalized.IsZero )
{
return isNegativeResult ? BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000)) : 0d; // underflow to -+0
}
Double result = 0 ;
bool isDouble = false ;
int scale = DoubleMaxScale ;
while ( scale > 0 )
{
if (!isDouble)
{
if ( SafeCastToDouble(denormalized) )
{
result = (Double) denormalized;
isDouble = true;
}
else
{
denormalized = denormalized / 10 ;
}
}
result = result / 10 ;
scale-- ;
}
if (!isDouble)
{
return isNegativeResult ? Double.NegativeInfinity : Double.PositiveInfinity;
}
else
{
return result;
}
}
private const int DoubleMaxScale = 308 ;
private static readonly BigInteger s_bnDoublePrecision = BigInteger.Pow( 10 , DoubleMaxScale ) ;
private static readonly BigInteger s_bnDoubleMaxValue = (BigInteger) Double.MaxValue;
private static readonly BigInteger s_bnDoubleMinValue = (BigInteger) Double.MinValue;
private static bool SafeCastToDouble(BigInteger value)
{
return s_bnDoubleMinValue <= value && value <= s_bnDoubleMaxValue;
}
}
The BigRational library has a conversion operator to double.
Also, remember to return infinity as a special case for a vertical line, you'll get a divide by zero exception with your current code. Probably best to just calculate the X1 - X2 first, and return infinity if it's zero, then do the division, to avoid redundant operations.
This does not deal with negative but hopefully give you a start.
double doubleMax = double.MaxValue;
BigInteger numerator = 120;
BigInteger denominator = 50;
if (denominator != 0)
{
Debug.WriteLine(numerator / denominator);
Debug.WriteLine(numerator % denominator);
BigInteger ansI = numerator / denominator;
if (ansI < (int)doubleMax)
{
double slope = (double)ansI + ((double)(numerator % denominator) / (double)denominator); ;
Debug.WriteLine(slope);
}
}
I have to convert a double value x into two integers as specified by the following...
"x field consists of two signed 32 bit integers: x_i which represents the integral part and x_f which represents the fractional part multiplied by 10^8. e.g.: x of 80.99 will have x_i as 80 and x_f as 99,000,000"
First I tried the following, but it seems to fail sometimes, giving an xF value of 1999999 when it ought to be 2000000
// Doesn't work, sometimes we get 1999999 in the xF
int xI = (int)x;
int xF = (int)(((x - (double)xI) * 100000000));
The following seems to work in all the cases that I've tested. But I was wondering if there's a better way to do it without the round call. And also, could there be cases where this could still fail?
// Works, we get 2000000 but there's the round call
int xI = (int)x;
double temp = Math.Round(x - (double)xI, 6);
int xF = (int)(temp * 100000000);
The problem is (1) that binary floating point trades precision for range and (2) certain values, such as 3.1 cannot be repsented exactly in standard binary floating point formats, such as IEEE 754-2008.
First read David Goldberg's "What Every Computer Scientist Should Know About Floating-Point Arithmetic", published in ACM Computing Surveys, Vol 23, No 1, March 1991.
Then see these pages for more on the dangers, pitfalls and traps of using floats to store exact values:
http://steve.hollasch.net/cgindex/coding/ieeefloat.html
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Why roll your own when System.Decimal gives you precise decimal floating point?
But, if your going to do it, something like this should do you just fine:
struct WonkyNumber
{
private const double SCALE_FACTOR = 1.0E+8 ;
private int _intValue ;
private int _fractionalValue ;
private double _doubleValue ;
public int IntegralValue
{
get
{
return _intValue ;
}
set
{
_intValue = value ;
_doubleValue = ComputeDouble() ;
}
}
public int FractionalValue
{
get
{
return _fractionalValue ;
}
set
{
_fractionalValue = value ;
_doubleValue = ComputeDouble() ;
}
}
public double DoubleValue
{
get
{
return _doubleValue ;
}
set
{
this.DoubleValue = value ;
ParseDouble( out _intValue , out _fractionalValue ) ;
}
}
public WonkyNumber( double value ) : this()
{
_doubleValue = value ;
ParseDouble( out _intValue , out _fractionalValue ) ;
}
public WonkyNumber( int x , int y ) : this()
{
_intValue = x ;
_fractionalValue = y ;
_doubleValue = ComputeDouble() ;
return ;
}
private void ParseDouble( out int x , out int y )
{
double remainder = _doubleValue % 1.0 ;
double quotient = _doubleValue - remainder ;
x = (int) quotient ;
y = (int) Math.Round( remainder * SCALE_FACTOR ) ;
return ;
}
private double ComputeDouble()
{
double value = (double) this.IntegralValue
+ ( ( (double) this.FractionalValue ) / SCALE_FACTOR )
;
return value ;
}
public static implicit operator WonkyNumber( double value )
{
WonkyNumber instance = new WonkyNumber( value ) ;
return instance ;
}
public static implicit operator double( WonkyNumber value )
{
double instance = value.DoubleValue ;
return instance ;
}
}
I think using decimals solve the problem, because internally they really use a decimal representation of the numbers. With double you get rounding errors when converting the binary representation of a number to decimal. Try this:
double x = 1234567.2;
decimal d = (decimal)x;
int xI = (int)d;
int xF = (int)(((d - xI) * 100000000));
EDIT: The endless discussion with RuneFS shows that the matter is not that easy. Therefore I made a very simple test with one million iterations:
public static void TestDecimals()
{
int doubleFailures = 0;
int decimalFailures = 0;
for (int i = 0; i < 1000000; i++) {
double x = 1234567.7 + (13*i);
int frac = FracUsingDouble(x);
if (frac != 70000000) {
doubleFailures++;
}
frac = FracUsingDecimal(x);
if (frac != 70000000) {
decimalFailures++;
}
}
Console.WriteLine("Failures with double: {0}", doubleFailures); // => 516042
Console.WriteLine("Failures with decimal: {0}", decimalFailures); // => 0
Console.ReadKey();
}
private static int FracUsingDouble(double x)
{
int xI = (int)x;
int xF = (int)(((x - xI) * 100000000));
return xF;
}
private static int FracUsingDecimal(double x)
{
decimal d = (decimal)x;
int xI = (int)d;
int xF = (int)(((d - xI) * 100000000));
return xF;
}
In this Test 51.6% of the doubles-only conversion fail, where as no conversion fails when the number is converted to decimal first.
There are two issues:
Your input value will rarely be equal to its decimal representation with 8 digits after the decimal point. So some kind of rounding is inevitable. In other words: your number i.20000000 will actually be slightly less or slightly more than i.2.
Casting to int always rounds towards zero. This is why, if i.20000000 is less than i.2, you will get 19999999 for the fractional part. Using Convert.ToInt32 rounds to nearest, which is what you'll want here. It will give you 20000000 in all cases.
So, provided all your numbers are in the range 0-99999999.99999999, the following will always get you the nearest solution:
int xI = (int)x;
int xF = Convert.ToInt32((x - (double)xI) * 100000000);
Of course, as others have suggested, converting to decimal and using that for your calculations is an excellent option.
I have a situation that I cannot change: one database table (table A) accepts 6 decimal places, while a related column in a different table (table B) only has 3 decimal places.
I need to copy from A to B, but if A has more than 3 decimal places the extra data will be lost. I cant change the table definition but I can add a workaround. So I'm trying to find out how to check if a decimal has more than 3 decimal places or not?
eg
Table A
Id, Qty, Unit(=6dp)
1, 1, 0.00025
2, 4000, 0.00025
Table B
Id, TotalQty(=3dp)
I want to be able to find out if Qty * Unit from Table A has more than 3 decimals (row 1 would fail, row 2 would pass):
if (CountDecimalPlaces(tableA.Qty * tableA.Unit) > 3)
{
return false;
}
tableB.TotalQty = tableA.Qty * tableA.Unit;
How would I implement the CountDecimalPlaces(decimal value) {} function?
You could compare the value of the number rounded to 3 decimal places with the original value.
if (Decimal.Round(valueDecimal, 3) != valueDecimal)
{
//Too many decimals
}
This works for 3 decimal places, and it can be adapted for a generic solution:
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));
}
For a real generic solution, you'll need to "deconstruct" the decimal value in its parts - take a look at Decimal.GetBits for more information.
Update: this is a simple implementation of a generic solution which works for all decimals whose integer part is less than long.MaxValue (you'd need something like a "big integer" for a trully generic function).
static decimal CountDecimalPlaces(decimal dec)
{
Console.Write("{0}: ", dec);
int[] bits = Decimal.GetBits(dec);
ulong lowInt = (uint)bits[0];
ulong midInt = (uint)bits[1];
int exponent = (bits[3] & 0x00FF0000) >> 16;
int result = exponent;
ulong lowDecimal = lowInt | (midInt << 32);
while (result > 0 && (lowDecimal % 10) == 0)
{
result--;
lowDecimal /= 10;
}
return result;
}
static void Foo()
{
Console.WriteLine(CountDecimalPlaces(1.6m));
Console.WriteLine(CountDecimalPlaces(1.600m));
Console.WriteLine(CountDecimalPlaces(decimal.MaxValue));
Console.WriteLine(CountDecimalPlaces(1m * 0.00025m));
Console.WriteLine(CountDecimalPlaces(4000m * 0.00025m));
}
This is a very simple one line code to get count of decimals in a Decimal:
decimal myDecimal = 1.000000021300010000001m;
byte decimals = (byte)((Decimal.GetBits(myDecimal)[3] >> 16) & 0x7F);
Multiplying a number with 3 decimal places by 10 to the power of 3 will give you a number with no decimal places. It's a whole number when the modulus % 1 == 0. So I came up with this...
bool hasMoreThanNDecimals(decimal d, int n)
{
return !(d * (decimal)Math.Pow(10, n) % 1 == 0);
}
Returns true when n is less than (not equal) to the number of decimal places.
The basics is to know how to test if there are decimal places, this is done by comparing the value to its rounding
double number;
bool hasDecimals = number == (int) number;
Then, to count 3 decimal places, you just need to do the same for your number multiplied by 1000:
bool hasMoreThan3decimals = number*1000 != (int) (number * 1000)
All of the solutions proposed so far are not extensible ... fine if you are never going to check a value other than 3, but I prefer this because if the requirement changes the code to handle it is already written. Also this solution wont overflow.
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;
}
carlosfigueira solution will need to check for 0 otherwise "while ((lowDecimal % 10) == 0)" will produce an infinity loop when called with 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));
One more option based on #RodH257's solution, but reworked as an extension method:
public static bool HasThisManyDecimalPlacesOrLess(this decimal value, int noDecimalPlaces)
{
return (Decimal.Round(value, noDecimalPlaces) == value);
}
You can then call that as:
If !(tableA.Qty * tableA.Unit).HasThisManyDecimalPlacesOrLess(3)) return;
There is probably a more elegant way to do this, but off the top of my head I would try
a = multiply by 1000
b = truncate a
if (b != a) then there is additional precision that has been lost
bool CountDecimalPlaces(decimal input)
{
return input*1000.0 == (int) (input*1000);
}
Here is my version:
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;
}
I tried first #carlosfigueira/#Henrik Stenbæk, but their version does not work with 324000.00m
TEST:
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
could you convert it to a string and just do a len function or would that not cover your situation?
follow up question:
would 300.4 be ok?
Public Function getDecimalCount(decWork As Decimal) As Integer
Dim intDecimalCount As Int32 = 0
Dim strDecAbs As String = decWork.ToString.Trim("0")
intDecimalCount = strDecAbs.Substring(strDecAbs.IndexOf(".")).Length -1
Return intDecimalCount
End Function
From a XML file I receive decimals on the format:
1.132000
6.000000
Currently I am using Decimal.Parse like this:
decimal myDecimal = Decimal.Parse(node.Element("myElementName").Value, System.Globalization.CultureInfo.InvariantCulture);
How do print myDecimal to string
to look like below ?
1.132
6
I don't think there are any standard numeric format strings which will always omit trailing insignificant zeroes, I'm afraid.
You could try to write your own decimal normalization method, but it could be quite tricky. With the BigInteger class from .NET 4 it would be reasonably feasible, but without that (or something similar) it would be very hard indeed.
EDIT: Okay, I think this is what you want:
using System;
using System.Numerics;
public static class DecimalExtensions
{
// Avoiding implicit conversions just for clarity
private static readonly BigInteger Ten = new BigInteger(10);
private static readonly BigInteger UInt32Mask = new BigInteger(0xffffffffU);
public static decimal Normalize(this decimal input)
{
unchecked
{
int[] bits = decimal.GetBits(input);
BigInteger mantissa =
new BigInteger((uint) bits[0]) +
(new BigInteger((uint) bits[1]) << 32) +
(new BigInteger((uint) bits[2]) << 64);
int sign = bits[3] & int.MinValue;
int exponent = (bits[3] & 0xff0000) >> 16;
// The loop condition here is ugly, because we want
// to do both the DivRem part and the exponent check :(
while (exponent > 0)
{
BigInteger remainder;
BigInteger divided = BigInteger.DivRem(mantissa, Ten, out remainder);
if (remainder != BigInteger.Zero)
{
break;
}
exponent--;
mantissa = divided;
}
// Okay, now put it all back together again...
bits[3] = (exponent << 16) | sign;
// For each 32 bits, convert the bottom 32 bits into a uint (which won't
// overflow) and then cast to int (which will respect the bits, which
// is what we want)
bits[0] = (int) (uint) (mantissa & UInt32Mask);
mantissa >>= 32;
bits[1] = (int) (uint) (mantissa & UInt32Mask);
mantissa >>= 32;
bits[2] = (int) (uint) (mantissa & UInt32Mask);
return new decimal(bits);
}
}
class Program
{
static void Main(string[] args)
{
Check(6.000m);
Check(6000m);
Check(6m);
Check(60.00m);
Check(12345.00100m);
Check(-100.00m);
}
static void Check(decimal d)
{
Console.WriteLine("Before: {0} - after: {1}", d, d.Normalize());
}
}
}
This will remove all the trailing zeros from the decimal and then you can just use ToString().
public static class DecimalExtensions
{
public static Decimal Normalize(this Decimal value)
{
return value / 1.000000000000000000000000000000000m;
}
}
Or alternatively, if you want an exact amount of precision, say 5 decimal places, first Normalize() and then multiply by 1.00000m.
This meets the example given but POORLY. (I THINK)
myDecimal.ToString("#.######")
What other requirements are there? Are you going to manipulate the values and show the manipulated values to this number of decimals?
Alternate answer involves recursiveness, like so:
//use like so:
myTextbox.Text = RemoveTrailingZeroes( myDecimal.ToString() );
private string RemoveTrailingZeroes(string input) {
if ( input.Contains( "." ) && input.Substring( input.Length - 1 ) == "0" ) { //test the last character == "0"
return RemoveTrailingZeroes( input.Substring( 0, input.Length - 2 ) )
//drop the last character and recurse again
}
return input; //else return the original string
}
And if you wanted an extension method, then this is an option
//use like so:
myTextbox.Text = myDecimal.ToString().RemoveTrailingZeroes();
private string RemoveTrailingZeroes(this string input) {
if ( input.Contains( "." ) && input.Substring( input.Length - 1 ) == "0" ) { //test the last character == "0"
return RemoveTrailingZeroes( input.Substring( 0, input.Length - 2 ) )
//drop the last character and recurse again
}
return input; //else return the original string
}
Added input.Contains( "." ) && per comment from Jon Skeet, but bear in mind this is going to make this incredibly slow. If you know that you'll always have a decimal and no case like myDecimal = 6000; then you could drop that test, or you could make this into a class and have several private methods based on whether the input contained a decimal, etc. I was going for simplest and "it works" instead of Enterprise FizzBuzz
If you only need to do this for display then how about using a custom format string?
// decimal has 28/29 significant digits so 30 "#" symbols should be plenty
public static readonly string TrimmedDecimal = "0." + new string('#', 30);
// ...
decimal x = 1.132000m;
Console.WriteLine(x.ToString() + " - " + x.ToString(TrimmedDecimal)); // 1.132
decimal y = 6.000000m;
Console.WriteLine(y.ToString() + " - " + y.ToString(TrimmedDecimal)); // 6
What about using toString("G29") on your decimal?
this does exactly what you're trying to achieve !