-1

I'm a total novice. I've created a C# program on SharpDevelop which uses the BigInteger structure.

Here it is:

using System;
using System.Numerics;
using System.Linq;


namespace HCC
{
class Program
{
    public static void Main(string[] args)
    {

        BigInteger[] HCC = new[]
        {
            BigInteger.Parse("2"),
            BigInteger.Parse("4"),
            BigInteger.Parse("6"),
            BigInteger.Parse("12"),
            BigInteger.Parse("24"),
        };

        double S;

        int i;

        S=0;

        for(i=0; i<HCC.Length; i++)
        {
            S=S+1.0/HCC[i];
        }

        Console.Write(""+S);

        Console.ReadKey(true);          

    }
}
}

Note: I've just put the first 5 ones, but there are actually 1000 big integers. And some have more than 70 digits.

The problem is that SharpDevelop is displaying this error:

Operator '/' cannot be applied to operands of type 'double' and 'System.Numerics.BigInteger' (CS0019)

It is relative to this line:

S=S+1.0/HCC[i];

What does this mean? Does this mean that we can't perform basic operations like addition, multiplication and division on BigIntegers?

And most importantly: How can I solve this problem?

leppie
  • 115,091
  • 17
  • 196
  • 297
user50746
  • 281
  • 2
  • 4
  • 10
  • No, it doesn't mean that, it means exactly what it says: you cannot divide a `double` by a `BigInteger`. As for how to solve it: are you interested in an approximation, or an exact result? If the former, is there any particular reason you're using `BigInteger`? If the latter, you'll need to re-think your approach. Have you considered that the name `BigInteger` already tells you the class won't support fractions? –  Oct 23 '14 at 12:22
  • @hvd : There will be no completely exact result because the true result has an infinite decimal expression. But I would want a really accurate result, yes. I'm looking for at least 7 accurate digits. I'm using BigInteger because the integers I'm using to perform the calculation are extremely big (some have more than 70 digits). – user50746 Oct 23 '14 at 12:26
  • There can be a completely exact result, expressible as a fraction. But if ~7 digits is sufficient, then I'd just use `double` for everything (which has a precision of ~15 digits): the last digits of one of those 70-digit integers won't make any appreciable difference. –  Oct 23 '14 at 12:30
  • @hvd Well, none of the digits will matter in a 70-digit number when you invert (`1 / x`) it :D – Luaan Oct 23 '14 at 12:40
  • @Luaan Sure they will: `1 / 1E70` and `1 / 2E70` will clearly give different results when the division is performed as `double`. –  Oct 23 '14 at 12:48
  • Well, maybe, but even if using double really doesn't lose precision I only have the list of the 1000 integers written as "BigInteger.Parse("2"), BigInteger.Parse("4")," etc. I did not make the list myself (I am not good enough), someone else made it and gave it to me. – user50746 Oct 23 '14 at 12:51
  • @hvd Yes, but both will be way below the precision of `double` as soon as you add them to `S`. The `S += 1.0 / HCC[i]` formula automatically means that if you start with `2`, there's little point in having numbers bigger than 15-digits (give or take) in HCC. While `1 / 1E70` can be represented as a double, `1 + 1 / 1E70` will simply end up being `1`. – Luaan Oct 23 '14 at 13:03
  • @Luaan Yes, that's correct. I hadn't realised that the OP's numbers really do start with 2, 4, and 6, instead of that just being sample data. –  Oct 23 '14 at 13:11
  • @Luaan: Very good point. I hadn't thought about that. So even using the type double or decimal will not work... So is there really no possible solution to my problem? – user50746 Oct 23 '14 at 15:58
  • @user50746 It *will* work, if the precision of the data type is at least a bit bigger than the precision you need of the result, and if you add the numbers up in a way to minimize rounding errors. Have a look at my updaed answer. – Luaan Oct 24 '14 at 07:32

1 Answers1

2

You most likely don't want to use BigInteger at all. Instead, decimal might be what you're looking for.

Something like this:

decimal[] HCC = new [] { 2M, 4M, 6M, 12M, 24M };

...

S += 1M / HCC[i];

Decimal is in base-10, rather than base-2, so it will guarantee you a decimal precision, rather than binary. It also has quite a huge range, so it should be good enough for your use.

Oh, and if you've got 70-digit numbers there, how do you expect them to affect a number you only need to be precise to 7 decimal digits? I think you're missing a point somewhere...

EDIT:

You're still missing a crucial point - if you really are working with a growing series of numbers, the numbers with digits above 20 will have no impact on the result anyway. The sum of the series converges on a given number, and you can approximate the first n significant digits easily (have a look at Taylor series for how this is used to e.g. compute sin (x), which is just another infinite decimal expression).

Now, if the series is finite and isn't necessarily growing, the simples thing you can do is to order it before doing the sum. Input the numbers in double - don't worry about lost precision, it will not affect the outcome (this takes a bit of mathematical analysis, but I have no idea what your background is, so if you can't prove this yourself, you might want to ask a question on math SE). Order them from largest to smallest. Sum them up one after another. The result should be quite precise to about 15 digits - you'll lose the far decimal digits quickly as you start adding up the larger 1 / x, but those will not affect the result anyway.

Of course, if you already know this, you can easily get to proving that you don't need to count the big numbers in the first place - they cannot affect decimals higer than their own digit count plus about 1-2. The exact behaviour is much more pronounced if the growth rate is really big (a very simple example being a geometric series with G(n) = 2 ^ n), but that seems to approximate your case rather well, given that you're working with small and extremely large numbers in the same series. If this is not good enough, you can try doing partial sums of numbers that are close enough to add with precision on e.g. decimal, and then adding up those sums - high-school algebra should be good enough for that :)

All in all, doing the math in your head (or on paper) helps a lot. Infinite decimal expression is something quite normal in math, and there's a lot of tools to work with those. And with approximation, rounding, limits and other stuff related to this.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • I believe that using the type "decimal" is useless here. The type "double" is better. The final true result will not be expressible as a finite expression in any base. – user50746 Oct 23 '14 at 12:54
  • @user50746 Well, try doing the math. If you only care about precision to 7 decimal places, what point is there to add an inverted 70-digit number? It will not make any difference anyway (assuming HCC is always growing). This isn't really about finite data types, it already fails on the math-level :D – Luaan Oct 23 '14 at 13:05