So the other day I was just experamenting with some code, just for fun, and I ran into some difficulties. So I suppose my question is why the following code does not write to the original bigints array. I am sure I am doing something dumb, but please bear with me. I made my own simple "state machine" thinking that I could return what is essentially a reference to the value in the array, and get away with only two BigIntegers being in memory at any given time. What seems to be happening though is that the value of the BigInteger is copied and then the copy is returned. I thought that whenever you did this "SomeObj obj = new SomeObj();" the left hand side was essentially a really safe pointer. Now this code is really convoluted, so as you can see I was just messing around, and wouldn't use this anywhere else. Perhaps when I access "array[current]" in the getCurrent() method the array copies the datatype instead? I know I am being too clever for my own good, be gentle. Are BigInts value types?

/*Author: overwraith*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;

namespace Fibonacci {

    class Program {

        static void Main(string[] args) {

            BigInteger[] bigints = new BigInteger[2] { new BigInteger(1), new BigInteger(2) };

            try{
                LoopingStateMachine<BigInteger> enumerable1 = new LoopingStateMachine<BigInteger>(bigints);

                //advance one on second state machine
                LoopingStateMachine<BigInteger> enumerable2 = new LoopingStateMachine<BigInteger>(bigints);
                enumerable2.MoveNext();

                while(enumerable1.MoveNext() && enumerable2.MoveNext()){
                    BigInteger current = enumerable1.getCurrent();

                    current += enumerable2.getCurrent();

                    Console.WriteLine("Fibonacci Number: " + current);
                }//end loop
            }catch(OutOfMemoryException){
                //can't go any higher
            }

            Console.Write("Press any key to continue... ");
            Console.ReadLine();

        }//end main

    }//end class

        public class LoopingStateMachine<T> {
            T[] array;
            UInt32 current = 0;

            public LoopingStateMachine(T[] arr){
                array = arr;
            }//end method

            public T getCurrent(){
                return array[current];
            }

            public bool MoveNext(){
                //reset the current index
                if (current == array.Length - 1)
                    current = 0;
                else
                    this.current++;

                return true;
            }//end method
    }//end class

}//end namespace

Recommended Answers

All 7 Replies

You're right, that when you do something = new Something(); that basically assigns a "very safe pointer" (a.k.a. reference) to something. In fact when you do something = anything;, you're assigning a reference.

Also note that x += y is just a shortcut for x = x + y;. So when you do:

BigInteger current = enumerable1.getCurrent();
current += enumerable2.getCurrent();

You're assigning a reference to current on the first line and then assigning another reference on the second line. In C, the equivalent would look something like this:

BigInteger* current = getCurrent(enumerable1);
current = add_big_integer(current, getCurrent(enumerable2));

Where add_big_integer has the signature BigInteger* add_big_integer(BigInteger*, BigInteger*). The important thing here is that the second line is not:

*current = *add_big_integer(current, getCurrent(enumerable2));

Assigning to a non-ref/out variable in C# never changes the object that the variable currently refers to - it simply makes it refer to something else. In order to change the object itself, you either need to assign to one of the object's properties (or variables if it has any public ones) or call a mutating method on it (i.e. method that changes the state of the object).

However the BigInteger class does not have any mutating methods, so you simply can't do this.

Wait a sec, is the + operation returning a new big integer object? Oh. I shoulda seen that.

is the + operation returning a new big integer object?

Yes, exactly.

Thanks for the help. I am really just messing around with this code now, I acutally am not very dumb.

So I figured that a loop might be better than calling recursive methods or something, am not sure. But I wrote this program using 3 big integers to see how big a fibonacci number I can make. Is currently dumping to my screen, and when it runs out of memory it will dump to a binary file. There are probably better ways of figuring fibonacci numbers, I will have to look into it.

/*Author: overwraith*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
using System.IO;

namespace Fibonacci {

    class Program {

        static void Main(string[] args) {

            const String ctFile = "Fibonacci_Current.dat";
            const String prevFile = "Fibonacci_Previous.dat";

            BigInteger previous = 1, current = 2, fibbonacci = 0;

            Console.WriteLine("Fibonacci Num: {0} ", previous);
            Console.WriteLine("Fibonacci Num: {0} ", current);

            try {
                if (File.Exists(prevFile) && File.Exists(ctFile)) {
                    //pick up where we left off
                    using (BinaryReader ctReader = new BinaryReader(
                        new BufferedStream(
                            new FileStream(ctFile, FileMode.Open,
                                FileAccess.Read, FileShare.ReadWrite)))) {
                        current = new BigInteger(ctReader.ReadAllBytes());
                    }//end using

                    using (BinaryReader prevReader = new BinaryReader(
                        new BufferedStream(
                            new FileStream(prevFile, FileMode.Open,
                                FileAccess.Read, FileShare.ReadWrite)))) {
                        previous = new BigInteger(prevReader.ReadAllBytes());
                    }//end using
                }//end if

                while (true) {
                    fibbonacci = previous + current;

                    Console.WriteLine("Fibonacci Num: {0} ", fibbonacci);

                    //swap
                    previous = current;
                    current = fibbonacci;
                }
            }
            catch (OutOfMemoryException) {
                //can't go any higher
            }
            finally {
                //write the resulting fibbonacci nums so other programs can pick 
                // up if more resources come available later
                using (BinaryWriter ctWriter = new BinaryWriter(
                    new BufferedStream(
                        new FileStream(ctFile, FileMode.Create,
                            FileAccess.ReadWrite, FileShare.ReadWrite)))) {
                    ctWriter.Write(current.ToByteArray());
                }//end using

                using (BinaryWriter prevWriter = new BinaryWriter(
                    new BufferedStream(
                        new FileStream(prevFile, FileMode.Create,
                            FileAccess.ReadWrite, FileShare.ReadWrite)))) {
                    prevWriter.Write(previous.ToByteArray());
                }//end using
            }//end finally

            Console.Write("Press any key to continue... ");
            Console.ReadLine();

        }//end main

    }//end class

    public static class BinaryReaderExt {

        public static byte[] ReadAllBytes(this BinaryReader reader) {
            List<byte> bytes = new List<byte>();

            try {
                while (true) {
                    bytes.Add(reader.ReadByte());
                }//end loop
            }
            catch (EndOfStreamException) {
                //swallow exception
            }

            return bytes.ToArray<byte>();
        }//end method
    }//end class

}//end namespace

Hi, I think the problem is not with C# itself, I think the problem that you created a getCurrent() method without creating setCurrent() method. If you programe with C/C++, setters and getters are common in their univers. It's also called properties in C#/Java world too. Anyway, here is some corrections of the code to write the Fibonacci seriese to console, I strarted the counter from 0, others probably want to start it with 1, it depends, anyhow, here's the code:

        static void Main(string[] args)
        {
            BigInteger[] bigints = new BigInteger[2] { new BigInteger(0), new BigInteger(1) };
            try
            {
                LoopingStateMachine<BigInteger> enumerable1 = new LoopingStateMachine<BigInteger>(bigints);
                Console.WriteLine("Fibonacci Number: " + enumerable1.getCurrent());
                //advance one on second state machine
                LoopingStateMachine<BigInteger> enumerable2 = new LoopingStateMachine<BigInteger>(bigints);
                enumerable2.MoveNext();
                int counter = 0;
                while (counter ++ < 10)
                {
                    BigInteger current = enumerable1.getCurrent();

                    current += enumerable2.getCurrent();
                    Console.WriteLine("Fibonacci Number: " + current);
                    enumerable1.MoveNext();
                    enumerable1.setCurrent(current);
                    enumerable2.setCurrent(current);

                    enumerable2.MoveNext();
                }//end loop
            }
            catch (OutOfMemoryException)
            {

                //can't go any higher
            }
            Console.Write("Press any key to continue... ");
            Console.ReadLine();
        }//end main
        public class LoopingStateMachine<T>
        {
            T[] array;
            UInt32 current = 0;
            public LoopingStateMachine(T[] arr)
            {
                array = arr;
            }//end method
            public T getCurrent()
            {
                return array[current];
            }

            public void setCurrent(T currBigInt)
            {
                array[current] = currBigInt;
            }
            public bool MoveNext()
            {
                //reset the current index
                //if (current == array.Length - 1)
                //    current = 0;
                //else
                //    this.current++;
                current = (current + 1) % (UInt32)array.Length;
                return true;
            }//end method
        }//end class

Hope this solve the problem.

That would be a good fix too. Thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.