For a general-purpose¹ solution you need to preserve 339 places:

`doubleValue.ToString("0." + new string('#', 339))`

The maximum number of non-zero decimal digits is 16. 15 are on the right side of the decimal point. The exponent can move those 15 digits a maximum of 324 places to the right. (See the range and precision.)

It works for `double.Epsilon`

, `double.MinValue`

, `double.MaxValue`

, and anything in between.

The performance will be much greater than the regex/string manipulation solutions since all formatting and string work is done in one pass by unmanaged CLR code. Also, the code is much simpler to prove correct.

For ease of use and even better performance, make it a constant:

```
public static class FormatStrings
{
public const string DoubleFixedPoint = "0.###################################################################################################################################################################################################################################################################################################################################################";
}
```

¹ **Update:** I mistakenly said that this was also a lossless solution. In fact it is not, since `ToString`

does its normal display rounding for all formats except `r`

. Live example. Thanks, @Loathing! Please see Lothing’s answer if you need the ability to roundtrip in fixed point notation (i.e, if you’re using `.ToString("r")`

today).

Here's a summary of Dimitris Andreou's link.

Remember sum of i-th powers, where i=1,2,..,k. This reduces the problem to solving the system of equations

a_{1} + a_{2} + ... + a_{k} = b_{1}

a_{1}^{2} + a_{2}^{2} + ... + a_{k}^{2} = b_{2}

...

a_{1}^{k} + a_{2}^{k} + ... + a_{k}^{k} = b_{k}

Using Newton's identities, knowing b_{i} allows to compute

c_{1} = a_{1} + a_{2} + ... a_{k}

c_{2} = a_{1}a_{2} + a_{1}a_{3} + ... + a_{k-1}a_{k}

...

c_{k} = a_{1}a_{2} ... a_{k}

If you expand the polynomial (x-a_{1})...(x-a_{k}) the coefficients will be exactly c_{1}, ..., c_{k} - see Viète's formulas. Since every polynomial factors uniquely (ring of polynomials is an Euclidean domain), this means a_{i} are uniquely determined, up to permutation.

This ends a proof that remembering powers is enough to recover the numbers. For constant k, this is a good approach.

However, when k is varying, the direct approach of computing c_{1},...,c_{k} is prohibitely expensive, since e.g. c_{k} is the product of all missing numbers, magnitude n!/(n-k)!. To overcome this, perform computations in Z_{q} field, where q is a prime such that n <= q < 2n - it exists by Bertrand's postulate. The proof doesn't need to be changed, since the formulas still hold, and factorization of polynomials is still unique. You also need an algorithm for factorization over finite fields, for example the one by Berlekamp or Cantor-Zassenhaus.

High level pseudocode for constant k:

- Compute i-th powers of given numbers
- Subtract to get sums of i-th powers of unknown numbers. Call the sums b
_{i}.
- Use Newton's identities to compute coefficients from b
_{i}; call them c_{i}. Basically, c_{1} = b_{1}; c_{2} = (c_{1}b_{1} - b_{2})/2; see Wikipedia for exact formulas
- Factor the polynomial x
^{k}-c_{1}x^{k-1} + ... + c_{k}.
- The roots of the polynomial are the needed numbers a
_{1}, ..., a_{k}.

For varying k, find a prime n <= q < 2n using e.g. Miller-Rabin, and perform the steps with all numbers reduced modulo q.

EDIT: The previous version of this answer stated that instead of Z_{q}, where q is prime, it is possible to use a finite field of characteristic 2 (q=2^(log n)). This is not the case, since Newton's formulas require division by numbers up to k.

## Best Solution

C# is treating the 1 and the 3 as integers, you need to do the following:

or

It is actually interesting because the implicit widening conversion makes you make a mistake.