1

I'm porting a JavaScript game into C#, an interesting feature of this game is that there are dozens of resources which grow from fractions per second to over e^thousands per second.

I need to be able to do standard math operations / string formats on these numbers many times a second ... mostly addition as resources accumulate and division to show how many of x I can buy with y or how long it'll take to complete a goal given a per second progress.

In C# I've tried using various 3rd party large number solutions (Rational / BigDecimal / BigFloat) all of which use System.Numerics.BigInteger under the hood ... and I've tried just using BigIntegers. All of these are functional but suffer from unacceptable performance.

My use-case doesn't need arbitrarily large (expected practical range is +/- e5000) or precise (6 decimal places is comfortably enough) numbers but I do need simple math operations to be significantly faster than BigInteger will provide. What are potential solutions to this problem?

Edit 1 - the JS game uses BigDecimal.js ... which also has performance issues later game when the numbers get really large.

Edit 2 - For anyone down-voting I'd really appreciate an explanation why.

Edit 3 - rephrased as a single question / to be more on topic.

Ben Roberts
  • 199
  • 1
  • 8
  • Have you tried `[System.Decimal](https://msdn.microsoft.com/en-us/library/system.decimal(v=vs.110).aspx)'? – Jonathan Tyson Aug 04 '17 at 23:15
  • @Jonathan Tyson It's good to like 28 decimal places.... – hoodaticus Aug 04 '17 at 23:16
  • [Here's something](http://quadruple.codeplex.com/) 128 bit floating point library – Jonathan Tyson Aug 04 '17 at 23:20
  • Is there a reason you can relate to us why you require numbers 25 times larger than the sum of all the atoms in the universe? – hoodaticus Aug 04 '17 at 23:23
  • @harold the JS code uses BigDecimal.js – Ben Roberts Aug 04 '17 at 23:23
  • @hoodaticus that's just what this game happens to be about - growing completely ridiculous numbers of things. – Ben Roberts Aug 04 '17 at 23:24
  • OOOH Aurigan that sounds like fun! You are caught between two extremes. Integers can represent the numbers with no loss of precision but yours will need to be over 2KB. The largest integer register on any commodity processor is 128 bytes and I'm not sure you can do math on the whole register as a single number. So you're talking about multi-word integer mathematics on probably QWords which means you don't have enough registers in the CPU (> 128) to hold everything needed to add 1 to that number. So floating point - with its loss of precision - is your only performant option. – hoodaticus Aug 04 '17 at 23:28
  • _"...suffer from unacceptable performance..."_ - hmm, well JavaScript is hardly a **bastion of performance** –  Aug 04 '17 at 23:28
  • https://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin –  Aug 04 '17 at 23:31
  • @JonathanTyson Decimal only has +/- e28 range, I need +/-e5000. The quadruple library on the other hand *does* look promising, thanks! – Ben Roberts Aug 04 '17 at 23:36
  • 1
    @hoodaticus this may be absurdly pedantic given the context, but... *observable* universe, surely... – Marc Gravell Aug 04 '17 at 23:37
  • I think javascript's BigDecimal is based on Java's BigDecimal. There is a way to use Java's BigDecimal from c#. See one of the answers to this question, which talks about it https://stackoverflow.com/questions/2967723/is-there-a-128-or-256-bit-double-class-in-net – hatchet - done with SOverflow Aug 04 '17 at 23:37
  • Note - my math was slightly off. Your desired number range is more than 25 *orders of magnitude* larger than the sum of the atoms in the *observable* universe, not 25 times. – hoodaticus Aug 05 '17 at 00:36
  • 1
    @hoodaticus :) still not close. Atoms in observable universe: ~e80, numbers I need: e5000 ... so 4920 orders of magnitude larger. – Ben Roberts Aug 05 '17 at 01:01
  • @JonathanTyson Just to let you know it looks like that quad struct will work out perfectly - 100's of times more performant than using the other solutions I mentioned, has more precision than I need by a long way and a +/- e2776511644261678592 range which is ... sufficient ;) Please add it as an answer so I can accept it! – Ben Roberts Aug 05 '17 at 02:01
  • Since you don't need a lot of precision what's the problem with using the existing floating point numbers?? – Loren Pechtel Aug 05 '17 at 03:04
  • @LorenPechtel a double will only store up to e308, I need to store / perform calculations on numbers much, much larger than that. – Ben Roberts Aug 05 '17 at 04:48

1 Answers1

2

Here is a library for quadruple floats (128 bits) with 64 bits of precision and a 64-bit exponent. I haven't used it, but it seems to be reasonably performant considering what you are trying to accomplish.

Jonathan Tyson
  • 463
  • 4
  • 9
  • Its a shame that codeplex closed. Id recommend https://github.com/AdamWhiteHat/BigDecimal/ https://github.com/AdamWhiteHat/BigRational/ for arbitrary precision or https://github.com/coder0xff/QPFloat/ if you had your heart set on quadruple precision floating points. – Adam White May 20 '23 at 22:40