开发者

How do I read/write C# BigIntegers to/from a file?

开发者 https://www.devze.com 2023-03-22 04:42 出处:网络
in one of my classes, I have a routine that reads and writes an array of type Decimal (using BinaryReader / BinaryWriter\'s ReadDecimal() and Write() methods, to w开发者_运维知识库it:

in one of my classes, I have a routine that reads and writes an array of type Decimal (using BinaryReader / BinaryWriter's ReadDecimal() and Write() methods, to w开发者_运维知识库it:

BinaryReader inputReader = new BinaryReader(File.OpenRead(BaseFilePath));
for (int x = 0; x < 6; x++) {
    for (int y = 0; y < m_Codes[x].GetLength(0); y++) {
        for (int z = 0; z < m_Codes[x].GetLength(1); z++) {
            m_Codes[x][y, z] = inputReader.ReadDecimal();
        }
    }
}

and

for (int x = 0; x < 6; x++) {
    for (int y = 0; y < m_Codes[x].GetLength(0); y++) {
        for (int z = 0; z < m_Codes[x].GetLength(1); z++) {
            outputWriter.Write(m_Codes[x][y, z]);
        }
    }
}

.. as you can see, only the first dimension is known at design time, the others vary on runtime.

In a perfect world, I would replace ReadDecimal() with ReadBigInteger() and something similar for the writing methods, but that does not seem to be supported in the Stream classes; I'm guessing this is because BigInteger can be of any length.

About the best thing I can think of is to "hand code" the BigInteger, by converting it to a byte[] array, then writing the length of that array, then writing each byte in the array itself (and doing the reverse to read it in)

Two questions:

1) Is this a better way?

2) I'm primarily motivated by a desire to increase performance; boes BigInteger even perform that much better than Decimal, if at all?


There's one fairly simple approach: Call BigDecimal.ToByteArray to serialize, and the BigDecimal(byte[]) constructor when deserializing. Admittedly that ends up copying the data, but I'd still expect it to be reasonably fast.

What's of more concern to you: serialization performance or arithmetic performance?

As for any speed differences between BigInteger and decimal - you should test it for the operations you actually want to perform, being aware that they will behave differently (e.g. dividing 3 by 2 will obviously give a different answer for each type).


You could convert to a string (BigInteger.ToSting()) and then write that string (as strings are directly supported with BinaryReader and BinaryWriter this avoids needing to do any encoding/decoding yourself).

Then convert it back with BigInteger.Parse.

To address the performance: I think you'll need to measure for the cases you are interested.

When relatively small values (say abs(value) < 2128) I would expect BigInteger's performance to be within a couple of orders of magnitude of long's performance (ie. no more than ~500 times slower). But as BigInteger instances get larger operations will take longer (more bits have to be manipulated). On the other hand decimal should have reasonably consistent performance at all scales, but it could be very much slower than long for numbers in the intersection of their ranges (decimal is a much more complex representation: scale factors and retaining actual significant digits through calculations; but no intuition of the effect of this complexity).

And remember: BigDecimal is exact – it never rounds; decimal is approximate – data can fall off the end and be thrown away. It seems unlikely that any one business problem would support either.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号