# Is it possible to have large numbers?

Discussion in 'World Editor Help Zone' started by mr po, Jun 20, 2018.

1. ### mr po

Joined:
Dec 8, 2016
Messages:
127
Resources:
1
Maps:
1
Resources:
1
It seems Warcraft 3 large numbers are limited around billions, how do i do mathematics in numbers larger than that, like trillions?

### JASS Reviewer

Joined:
Mar 25, 2016
Messages:
1,287
Resources:
0
Resources:
0
You should not use this large numbers. Integers can represent 2^32 different numbers, which should be enough for pretty much any map.

If you really need large numbers, you can use multiple integers and interpret them as one number. You will have to write custom functions to perform arithmetic operations on them.
The resulting big number cannot be used for any native function.
You will have to write custom functions that work with larger numbers.

3. ### Kaijyuu

Joined:
Jun 2, 2004
Messages:
848
Resources:
0
Resources:
0
There are, of course, the floating point numbers (reals), though they come with all the standard limitations.

4. ### nedio95

Joined:
Mar 24, 2011
Messages:
1,055
Resources:
1
Spells:
1
Resources:
1
Isn't it 2^31-1 ? The 32nd bit being reserved for positive/negative.
Edit//Ah, I see what you mean now, you are correct. I got confused by the wording.

Still, same limitation.

regards
-Ned

5. ### mr po

Joined:
Dec 8, 2016
Messages:
127
Resources:
1
Maps:
1
Resources:
1
Basically that's nearly no difference from writing a new calculator, but cant i really circumvent that limited integer number and use innate warcraft 3 calculator?

### Spell Reviewer

Joined:
Jan 18, 2005
Messages:
25,716
Resources:
3
Maps:
1
Spells:
2
Resources:
3
They use two's compliments for negative numbers. This means that although it is technically a sign bit, it does not out right represent positive/negative but instead represents {-(2 ^ 31)}.
Not true. Although floating points still have the same limitation on number of possible representable number states, the numeric range covered by floating points is completely different. For a standard IEEE 32 bit float the range is...

{(2 − (2 ^ −23)) × 2 ^ 127}

Which is considerably larger than both 32bit and even 64bit integers. This is achieved by sacrificing numeric accuracy, floats represent numbers accurately to only a small number of significant figures.

7. ### nedio95

Joined:
Mar 24, 2011
Messages:
1,055
Resources:
1
Spells:
1
Resources:
1
Interesting.
For some bizarre reason, I was left with the impression that Real in war3 did not use floating point.

regards
-Ned

### Spell Reviewer

Joined:
Jan 18, 2005
Messages:
25,716
Resources:
3
Maps:
1
Spells:
2
Resources:
3
Probably confused with StarCraft II. In StarCraft II the real type is fixed point with a maximum value of ~500,000.

9. ### Wark

Joined:
Oct 12, 2016
Messages:
738
Resources:
2
Maps:
2
Resources:
2
Why do you need an integer in the trillions?

10. ### Kaijyuu

Joined:
Jun 2, 2004
Messages:
848
Resources:
0
Resources:
0
One thing I came across recently was my custom experience curve. After 100 levels or so the total experience was in the trillions. I fixed it for my purposes by inferring total experience from level + xp to next level, instead of keeping explicit track of the total.

The answer to "why would you need x" is always that someone, somewhere has a plausible use case.

11. ### Wark

Joined:
Oct 12, 2016
Messages:
738
Resources:
2
Maps:
2
Resources:
2
Yea, I'm aware of it.
I'm just asking "why" since I am very good at finding alternatives with the same goal, especially concerning formulas or limitations.

### Spell Reviewer

Joined:
Jan 18, 2005
Messages:
25,716
Resources:
3
Maps:
1
Spells:
2
Resources:
3
Mostly it is just because they like silly numbers...
Or you could use a Xenoblade style system where the experience earned is based on the difference between monster level and character level. This removes the need to inflate the numbers so heavily as levels progress as players will not be able to farm low level monsters and gain levels.

13. ### mr po

Joined:
Dec 8, 2016
Messages:
127
Resources:
1
Maps:
1
Resources:
1
Thank you guys for tips and help. Consider the problem solved, i have made triggers to extend the numbers.

Because i am developing a business type map, i think it is silly to say "maximum profit you can earn is only 2 billion. Sorry. Game over."

14. ### EdgeOfChaos

Joined:
Jan 8, 2014
Messages:
639
Resources:
1
Tutorials:
1
Resources:
1
Some of the 'incremental' rpgs like golden gods rpg use extremely high numbers. Be warned that there is no good way to save these numbers, if your map uses a save system. I have tried every save system on THW and other sites, and none of them actually work for all cases (some even start generating faulty codes before the numbers hit 1 million). I guess save systems are very hard to make

I wrote a BigFloat library a while ago to do this, maybe it is useful (or not)

Code (vJASS):

* Representation of a very large number (greater than MAXINT)
* This is achieved by putting the numbers into scientific notation, making them
* easier to represent
* For a standard real, any values above 2.14b or so will become negative.
* This is intended to solve this problem and make very large
* numbers possible to work with.
* Does not handle negative numbers. Behavior with negatives is undefined
*/
struct BigFloat

//Stores the number part of the scientific number
private real number
//Stores the exponential part - i.e. 10^25
private integer exponent

/**
* Default no-args constructor for a large number
*/

public static method create takes real n, integer e returns thistype
local thistype new = thistype.allocate()
call new.change(n,e)
return new
endmethod

public method empty takes nothing returns nothing
set this.number = 0.
set this.exponent = 0
endmethod

/**
* Gets the number value of this BigFloat
*/

public method getNum takes nothing returns real
return this.number
endmethod

/**
* Gets the exponent of this BigFloat
*/

public method getExp takes nothing returns integer
return this.exponent
endmethod

/**
* Detects whether this big number is empty or not
* Defined as empty if it is 0 * 10^0
*/

public method isEmpty takes nothing returns boolean
return (this.getNum() <= 1 and this.getExp()==0)
endmethod

/**
* Takes as much of this BigFloat as possible and return it as a real
* This will be either 2147483646 or all remaining
*/

public method take takes nothing returns real
local real toRemove = 2147483646
if(isEmpty()==false)then
if((this.exponent < 9) or (this.exponent==9 and this.getNum <= 2.147483646))then
set toRemove = this.number * Pow(10,this.exponent)
set this.exponent = 0
set this.number = 0
endif
set toRemove = toRemove / Pow(10,this.exponent)
set this.number = this.number - toRemove
if(this.number <= 0)then
set this.number = 10 - this.number
set this.exponent = this.exponent-1
endif
endif
return I2R(R2I(toRemove))
endmethod

private method change takes real n, integer e returns nothing
set this.number = n
set this.exponent = e
call this.compress()
endmethod

private method compress takes nothing returns nothing
loop
exitwhen this.getNum() < 10.
set this.number = this.number / 10
set this.exponent = this.exponent + 1
endloop

if(this.getNum() <= 0) then
set this.number = 0
set this.exponent = 0
elseif(this.getNum() < 1) then
loop
exitwhen this.getNum() >= 1.
set this.number = this.number * 10
set this.exponent = this.exponent - 1
endloop
endif
endmethod

/**
* Returns the scientific notation
* of the big number.
*/

public method toString takes nothing returns string
return R2S(number) + " * 10^" + I2S(exponent)
endmethod

/**
* Destroys this big number.
*/

public method destroy takes nothing returns nothing
call this.deallocate()
endmethod

/**
* Creates a new BigFloat from the specified real num
* Num must be less than MAXINT.
*/

public static method convert takes real num returns thistype
local real numFinal = num
local integer expFinal = 0
return thistype.create(numFinal,expFinal)
endmethod

/**
* Changes the specified scientific notation string
* into a BigFloat
* Strings MUST be in the format:
* 5 * 10^15 for example
*/

public static method fromScientific takes string num returns thistype
local real numberSection = 0.
local integer exponentSection = 0
local integer pointer = 0
local integer breakCheck = 0
local string temp = ""

loop
exitwhen ((breakCheck > 200) or (SubString(num,pointer-1,pointer)==" "))
set temp = SubString(num,0,pointer)
set pointer = pointer + 1
set breakCheck = breakCheck + 1
endloop

set numberSection = S2R(temp)

loop
exitwhen ((breakCheck > 200) or (SubString(num,pointer-1,pointer)=="^"))
set pointer = pointer + 1
set breakCheck = breakCheck + 1
endloop

set temp = SubString(num,pointer,200)
set exponentSection = S2I(temp)

return thistype.create(numberSection,exponentSection)
endmethod

/**
* Multiplies this with another big number
* If destroy is set to true, the second BigFloat will be destroyed after the t
*/

public method multiply takes BigFloat by, boolean destroy returns nothing
local real numFinal = by.getNum() * this.getNum()
local integer expFinal = by.getExp() + this.getExp()

if(destroy)then
call by.destroy()
endif
call this.change(numFinal,expFinal)
endmethod

/**
* Divides this with another big number
* If destroy is set to true, the second BigFloat will be destroyed after the t
*/

public method divide takes BigFloat by, boolean destroy returns nothing
local real numFinal = this.getNum() / by.getNum()
local integer expFinal = this.getExp() - by.getExp()
if(destroy)then
call by.destroy()
endif
call this.change(numFinal,expFinal)
endmethod

/**
* If destroy is set to true, the second BigFloat will be destroyed after the t
*/

public method add takes BigFloat by, boolean destroy returns nothing
local real numFinal = 0.
local integer expFinal = 0
local integer diff = this.getExp() - by.getExp()
if(diff==0)then
set numFinal = this.getNum() + by.getNum()
set expFinal = this.getExp()
elseif(diff>0)then
set numFinal = this.getNum() + (by.getNum() / (Pow(10,diff)))
set expFinal = this.getExp()
else
set diff = -diff
set numFinal = by.getNum() + (this.getNum() / (Pow(10,diff)))
set expFinal = by.getExp()
endif

if(destroy)then
call by.destroy()
endif
call this.change(numFinal,expFinal)
endmethod

/**
* Subtracts another big number
* If destroy is set to true, the second BigFloat will be destroyed after the t
*/

public method subtract takes BigFloat by, boolean destroy returns nothing
local real numFinal = 0.
local integer expFinal = 0
local integer diff = this.getExp() - by.getExp()
if(diff==0)then
set numFinal = this.getNum() - by.getNum()
set expFinal = this.getExp()
elseif(diff>0)then
set numFinal = this.getNum() - (by.getNum() / (Pow(10,diff)))
set expFinal = this.getExp()
else
call change(0,0)
endif

if(destroy)then
call by.destroy()
endif
call this.change(numFinal,expFinal)
endmethod

public method percentOf takes BigFloat small, boolean destroy returns real
local real percent = 0.
call small.divide(this,false)
set percent = small.take() * 100
if(destroy)then
call small.destroy()
endif
return percent
endmethod

public method displayAt takes real x, real y returns nothing
local texttag txt = CreateTextTag()
call SetTextTagText(txt,toString(),TextTagSize2Height(10))
call SetTextTagPos(txt,x,y,0)
call SetTextTagPermanent(txt,false)
call SetTextTagVelocity(txt,0,TextTagSpeed2Velocity(40))
call SetTextTagLifespan(txt,1.5)
set txt = null
endmethod

/**
* Copies the old BigFloat to a new one
*/

public static method copy takes thistype old returns thistype
return thistype.create(old.getNum(),old.getExp())
endmethod
endstruct
/**

iirc just create a BigFloat either from scientific notation or from another real (obviously limited by size), then you can multiply/add to it, etc, to go over the limit

Last edited: Jun 24, 2018
15. ### nedio95

Joined:
Mar 24, 2011
Messages:
1,055
Resources:
1
Spells:
1
Resources:
1
Usually it is game design.

I started playing World of Warships (it's a multiplayer Naval battles with semi-simulator/arcade mechanics game, usually PvP 15v15) a few years ago and when I saw the HP and damage it made little sense to me. (Ships HP ranges around 10000 to 90000 and DPM ranges 100000 to 400000) Those numbers are pretty unhandy for precise fast-paced in-match calculations.
The Dev of World of Warships has another game World of Tanks (multiplayer Tank battles game with semi-simulator/arcade mechanics, usually PvP 15v15) where the numbers are much more handy ( in the ranges around 100-3000 for HP and DPM 800 - 5000) Which again are a bit confusing as usually in PvP shooting games you'd have something like 100 or more round and handy numbers.

But when you put it in context, it all makes sense.
You are not in control of a single person. You have a mighty tank made of steel!
You are in a bloody battleship. Bismark, Yamato, Tirpitz, Misouri ! You are in control of a 70 000 ton beast with 2000 crew members and shells bigger than you! Those are the only appropriate numbers in the case!

Also, do you know what gamers like ? Big numbers. Do you know what gamers like enve more ? Seeing big numbers become bigger

Of course, there are a bajillion games where there is absolutely no reason for use of those numbers, like why the hell should my Lvl 1 character deal 1531564645 damage with basic attack and 56465464 with that skill and 15486486464 with that other skill... like, wtf?
I can agree on high/max lvl having pumped up numbers, but there is absolutely no reason to have exclusively big numbers. Use them wisely

regards
-Ned

### Spell Reviewer

Joined:
Jan 18, 2005
Messages:
25,716
Resources:
3
Maps:
1
Spells:
2
Resources:
3
These numbers are sensible. One could even argue they are scaled such that the tanks could fight the battleships in a realistic way, not that it is possible.

Not sensible numbers would be ship health like 900,000,000,000,000,000,000,000,000,000,000,000,000,000 which is like what I have seen some WC3 RPGs have for unit health and damage.
Actually gamers do not like big numbers as it makes mental maths impossible. It even makes balance more error prone as it becomes increasingly more easy for a developer to leave a 0 off of a number by mistake when there are 10-40 of them.

17. ### nedio95

Joined:
Mar 24, 2011
Messages:
1,055
Resources:
1
Spells:
1
Resources:
1
True that those numbers are a lot more sensible than 5646489 bazzilions.
Well, it is still a pretty unhandy number for the average player. Most of the time it is not a 0s there, more like 65850 hp and 345698 DPM for ships and 1450 HP and 1878 DPM for tanks.
Still, as long as it is used within a good game design reason, large numbers are ok.
Have in mind that an average person would not have to deal with large numbers on a daily basis.

PS: We all love those war3 maps where you start with a black field for health and some numbers for hero stats that were created by rolling your head on the num pad... usually I quit immediately...

Big numbers getting bigger is usually the result of your character/resources/stats getting better.
Take WoW for example, or most MMORPGs, usually early game you'd be comparing single to quad digits while end game you are usually comparing millions and more. But the more sensible ones would give you a number like 1,500,000 instead of 6,851,313.

regards
-Ned

18. ### Wark

Joined:
Oct 12, 2016
Messages:
738
Resources:
2
Maps:
2
Resources:
2
Back on topic,
In terms of just using formulas in triggers, I'd recommend using something along the lines of scientific notation to bypass the integer or real limits (powers of 10).

For display, are you planning to use a multiboard for player stats?
I imagine you could have a multiboard indicate your net worth is in the billions or trillions, while the gold display or something shows you how many millions/thousands you've got.
Alternatively, are you using the lumber resource for anything?
It'd be easy to make a formula to indicate large numbers on the screen between gold and lumber. You can even change those icons and info text in the interface.

19. ### mr po

Joined:
Dec 8, 2016
Messages:
127
Resources:
1
Maps:
1
Resources:
1
Definitely multiboard will be used to display your net worth or current portfolio, but for the resources display, lumber will be part of the game. So dont think i can use the gold display to show billion dollar cash flow, what i can do is implement compulsory savings plan whenever the gold display exceeds 6 digit.

20. ### Daffa

Joined:
Jan 30, 2013
Messages:
7,746
Resources:
28
Packs:
1
Maps:
8
Spells:
17
Tutorials:
2
Resources:
28
If you take the recent patch, that'll be 7 digits.