0

I have the number 123.1234567890129.

I want the result to be 123.123456789012 without the last digit being rounded.

I've tried:

("123.1234567890129").ToString("G15") //123.123456789013
Steve
  • 2,950
  • 3
  • 21
  • 32
  • Possible duplicate of [C# Double - ToString() formatting with two decimal places but no rounding](http://stackoverflow.com/questions/2453951/c-sharp-double-tostring-formatting-with-two-decimal-places-but-no-rounding) – Broots Waymb Oct 14 '16 at 15:00
  • is there any pattern or you want any particular length of number after decimal ? – Vivek Nuna Oct 14 '16 at 15:01
  • I want exact 15 digits, for example if i the number is 12345.12345678909, the result that i expect is 12345.1234567890 – Mauricio Bacelis Oct 14 '16 at 15:05
  • full number would be 15 digits regardless decimals – Mauricio Bacelis Oct 14 '16 at 15:08
  • Is your code actually supposed to be calling `ToString` on the string representation of your decimal, or is that a typo? I don't believe that code will compile. Did you mean `(123.1234567890129).ToString("G15");`? – Broots Waymb Oct 14 '16 at 15:15
  • 1
    Basically, what I'm getting at, is that in no point in your example do you have a double. String representations of a double perhaps. But that is not the same thing. – Broots Waymb Oct 14 '16 at 15:41

5 Answers5

0

One way that you could do this is to round to 16 like this

("123.1234567890129").ToString("G16").Substring(0, 16);
Alfie Goodacre
  • 2,753
  • 1
  • 13
  • 26
  • 2 problems I can see here, please address me if I am mistaken... Your substring is including the decimal, so it will output `123.12345678901` not `123.123456789012`. Second (and I believe this is also an issue with the original post) is that you're calling `ToString("G16")` on a string, rather than the double. If I try that, I get a "cannot convert from 'string' to 'System.IFormatProvider'" error. – Broots Waymb Oct 14 '16 at 15:13
  • 1
    Yes that's correct, thanks I'll change that one :) this is just conceptual, not the actual instance it is happening in I would assume, as it's not got a semicolon and it's not even being assigned to anything in OP's example – Alfie Goodacre Oct 14 '16 at 15:15
  • Just another point to add (not that it's wrong in this specific scenario)... but since OP always wants 15 digits, the substring won't perform as expected if the double does not have a decimal. – Broots Waymb Oct 14 '16 at 15:21
  • This is a string, not a double. This won't work in all cases of double. – Rick the Scapegoat Oct 14 '16 at 15:30
0
  1. Since you said double.
  2. Since doubles can have ANY number of digits you must round in some way. (you either round down, as inferred or you round up as in practice for this case)
  3. Since you imply you only want to see the number of precise digits, you must find out how many digits are on each side of the decimal point (0 to 15 on either side)

An extenstion to round down

public static class DoubleExtensions
{
    public static double RoundDown(this double value, int numDigits)
    {
        double factoral = Math.Pow(10, numDigits);
        return Math.Truncate(value * factoral) / factoral;
    }
}

test case

        const int totalDigits = 15;

        // why start with a string??
        string somestring = "123.1234567890129";
        const int totalDigits = 15;

        // since the title says 'convert a double to a string' lets make it a double eh?
        double d = double.Parse(somestring);
        int value = (int)d;

        double digitsRight = d - value;
        int numLeft = (d - digitsRight).ToString().Count();
        int numRight = totalDigits - numLeft;

        double truncated = d.RoundDown(numRight);

        string s = truncated.ToString("g15");
Rick the Scapegoat
  • 1,056
  • 9
  • 19
0

You can create custom FormatProvider and then create your implementation.

class Program
{
    static void Main(string[] args)
    {
        double number = 123.1234567890129;

        var result = string.Format(new CustomFormatProvider(15), "{0}", number);
    }

}


public class CustomFormatProvider : IFormatProvider, ICustomFormatter
{
    private readonly int _numberOfDigits;

    public CustomFormatProvider(int numberOfDigits)
    {
        _numberOfDigits = numberOfDigits;
    }

    public object GetFormat(Type formatType) => formatType == typeof(ICustomFormatter) ? this : null;

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (!Equals(formatProvider))
            return null;

        if (!(arg is double))
        {
            return null;
        }

        var input = ((double)arg).ToString("R");

        return input.Length > _numberOfDigits + 1 ? input.Substring(0, _numberOfDigits + 1) : input; // +1 because of dot
    }

Unfortunately you cannot do in this way:

var result = number.ToString(new CustomFormatProvider(15));

because of value types limitation.. Double supports only CultureInfo and NumberFormatInfo formatters. If you pass different formatter it will return default instance: NumberFormatInfo.CurrentInfo'. You can make small workaround by usingstring.Format` method.

Pawel Maga
  • 5,428
  • 3
  • 38
  • 62
0

New to the community. First answer here. :)

I think you are looking for something like this. Works with or without decimal. This will cut the digits after the 15th digit only irrespective of length of the number. You can get the user to decide the accuracy by getting the precision value as a user input and performing that condition check accordingly. I used 15 because you mentioned it. Let me know if it works for you. Cheers!

        string newstr;
        int strlength,substrval;
        double number;
        string strnum = "123.1234567890129";
        strlength = strnum.Length;
        if(strlength>15)
        {
            strlength = 15;
        }
        substrval = strlength;
        foreach(char x in strnum)
        {
            if(x=='.')
            {
                substrval++;
            }
        }
        newstr = strnum.Substring(0, substrval);
        number=Convert.ToDouble(newstr);
-2
Alife Goodacre, code is printing "123.12345678901" insted "123.123456789012"

there should be Substring(0, 16) insted of Substring(0, 15)

Convert.ToDouble("123.1234567890129").ToString("G16").Substring(0, 16)

OutPut Screen with Code.

enter image description here

Bhanu Pratap
  • 1,635
  • 17
  • 17