S
S
Sergey Vinogradov2014-07-04 15:02:30
.NET
Sergey Vinogradov, 2014-07-04 15:02:30

How to bypass the double precision limit in C#?

There are two problems.
1. Two numbers are given - the range in which the solution of the equation is located. The search for a solution is made by dividing the segment in half. This is due to the fact that other methods of solution (for example, the method of chords or the method of tangents) are extremely inefficient and most often do not converge.
The problem is that if the boundaries of the segment are very small values, then when obtaining the middle of the segment, we get one of the boundary values, instead of the average. For example:


x1 = 0.00000000000000030426102110965129;
x2 = 0.00000000000000030426102110965134;
We get x = 0.00000000000000030426102110965134
x1 = -0.000000000000000070906981940269862;
x2 = -0.000000000000000070906981940269849;
We get x = -0.000000000000000070906981940269862

Tried to convert significant digits to long to get (x1+x2) / 2 and convert back to double. However, this method also leads to errors at certain points + slow (due to the calculation of the degree of the number). Does anyone know an easier way to do this?
2. An array of numbers is being calculated. Each subsequent element of the array in a certain way depends on all the previous ones. As a result, the values ​​grow quite quickly with increasing array length, and go beyond ±1.7×10E308. Further, this array is normalized, i.e. A[i] / summa (A[i]^2, i=0..N-1) . The resulting array is generally placed in double frames.
Are there any easy ways to solve this problem? For now, you have to use your own structure, which is two numbers int (power) and double (value from ~0.99 to ~9.99). However, this has a very detrimental effect on overall performance and, moreover, is extremely inconvenient.
Also, maybe someone knows a simple way to get significant digits and the degree of double? For it is necessary either to decrease / increase the number by tens in a cycle and count the degree, or to use the conversion of the number into a string, followed by its splitting by 'E' and parsing, which, at the same time, does not exclude the need for the first option.
UPD:
As a result of testing and discussion, the following became clear:
2. It is solved only through the created new type.
1. Own type won't help. When converting back, everything will return back. But it was possible to find out where the legs of the problem grow from.
The fact is that these numbers in binary notation differ by only 1 bit. And even if you crack, you will never get an average value.
Example:

x1 = 0.00000000000000030426102110965129;
Having received an array of bytes of value, we have:
119 95 82 12 160 236 181 60
x2 = 0.00000000000000030426102110965134;
Similarly:
120 95 82 12 160 236 181 60

What to do in such a situation is absolutely not clear.

Answer the question

In order to leave comments, you need to log in

5 answer(s)
D
Deerenaros, 2014-07-06
@Deerenaros

So. Stop.
Decimal can take a huge range of values, but due to decimal-to-binary conversions, the accuracy may still not be enough.
Alternatively, you can use BigInteger and store the comma as a separate number, you can also use BigInteger. In fact, a comma is an exponent at the base of the number system, that is, 10. Arithmetic is elementary.
There are thousands of implementations (including BigRational in C# F# ).
Almost all of them can be loaded from a string, and for those who cannot, we split by a point and count the number of zeros. But I must warn you - this method can go in cycles and for a very long time.

A
Alexey Kulakov, 2014-07-04
@carbon88

1) There is a Decimal type. You can try it. It will have more precision than double. If you need even more, then you already need to implement the mathematics of large numbers.

D
Denis Morozov, 2014-07-04
@morozovdenis

create your own complex data type
let it store two numbers double(number for example 1.5) and int(number 9 for example, which means 1.5/(10^9))
i.e. that (1.5, 9) == 0.0000000015
divide, add, etc. them

K
Killy, 2014-07-05
@Killy

2) ideone.com/YjX5k6 or stackoverflow.com/questions/389993/extracting-mant...
1) Is it possible to modify the algorithm so that calculations are carried out in conditional coordinates from 0.0 to 1.0 (for example), instead of real x1 .. x2 , and then calculate the real x in any slow way?

B
BigObfuscator, 2014-07-10
@BigObfuscator

What to do in such a situation is absolutely not clear.

And you transform the equation so that the ill-conditioned section becomes well-conditioned (by the way, this is called regularization).
For example, according to the formula x' = 1/(x - x1)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question