User:Shynoe/sandbox3

From FFXI Wiki

In FFXI, equipment or abilities that give bonuses as a percentile will usually perform slightly differently than stated. For example, a Damage Taken -5% Jelly ring will reduce the damage of 1000 Needles by 46 rather than 50. Players who verify game mechanics will give these numbers as a fraction of 256, like 12/256 in the last example, or as a fraction of 1024 in other cases. These imprecise numbers are typically used for values that fluctuate frequently, as is the case with adjustments to derived stats like Attack or Haste.



Technical Details

The server that ran the game calculations at launch was a system with an UltraSparc III processor (not to be confused with the UltraSparc IIi). A 32-bit (bit=binary digit) processor with 2 types of dedicated math cards: an FPU (Floating-Point Unit) and an IU (Integer Unit). These are specialized hardware specially built to do math: similar to the way a graphics card can run a shader program on 3 million+ pixels all at once, a math processor is built for doing parallel math operations more quickly than typical processors but they can only do functions related to math.

The Floating-Point Unit can do calculations with single-precision (32-bit) floating point number types. This gives it very high precision when it comes to fractions, for percentages is equivalent to around 10 decimal places. Floating-point means it stores numbers in a way where the precision can start at various points: Scientific Notation (3.75E20 or 3.75 × 1020) would be an example of this.

The Integer Unit is another specialized 32-bit processor which has a higher clock speed, but it only do math on whole numbers. It takes 32-bit data, and the data is divided between 4 registers. It can use these registers separately, doing a calculation on 4 8-bit numbers simultaneously, or as 2 16-bit numbers, or as 1 32-bit number. Even and odd processor pairs can work together to allow up to 8 numbers to run a function simultaneously. The 32-bit data can be packed as 1 32-bit number (0-4,294,967,295) or 2 16-bit numbers (0-65,535) or 4 8-bit numbers (0-255) or you could even pack it as 3 10-bit numbers (0-1023) with a 2-bit (0-3) number left over for extra data.

Float to Integer Conversion

Floating point numbers are stored in binary as:

  • 1 bit for the sign: 0 = Positive, 1 = Negative
  • 8 bits for the exponent:
  • 23 bits for the mantissa

Percentages coming from the database could be stored as ascii characters or floating point numbers, then converted to integers in order to do a calculation on the IU. 23 bits may seem like plenty of space to represent a 0-100 percentage, but binary numbers represent powers of 2. Decimal numbers have inaccuracies for fractions like 1/3, where the number of decimal digits make the difference between 0.3, 0.33, 0.333. Binary numbers are not accurate for numbers that are indivisible by powers of 2, so they will have the same issue for numbers like 0.03 (3%), limiting them to 0.0299999999, which may result in problems where a 3% value is rounded down to 2%, like with Movement Speed. Machines will stringify the number like that to something shorter for the user's benefit in usual cases.

To write one of these decimal fractions in binary, you can start by listing the powers of 2.

For the sake of example and page space, we'll use a half-precision float (16-bit), with a 4-bit exponent leaving 10-bits for the mantissa.

Powers of 2
2-1 2-2 2-3 2-4 2-5 2-6 2-7 2-8 2-9 2-10
1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256 1/512 1/1024
0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.000976563

Similar to long division, we'll multiply the operand by a number and subtract the difference. This is simple in binary, you'll either multiply by 0 or 1 and then subtract.

For this example, we'll convert 0.30 (30%, the value of Haste II) to binary.

Is 0.30 greater than 0.5? No, putting a 0 at the top. 0 in binary is 0 in decimal also.

Step 1
Binary Number: 0
Powers of 2: 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.000976563
Remainder: 0.30

Is 0.30 greater than 0.25? Yes, put a 1 at the top. Carry over the previous number (0) by multiplying it by 2 (0) and adding the number at the top (1). Repeat the process for the rest of the steps.

Step 2
Binary Number: 0 1
Powers of 2: 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.000976563
Remainder: 0.30 0.05
Integer: 0
(/2)
1
(/4)

With 0.05 left over, compare to the next row's 0.125. 0.05 is smaller so subtract (0 * 0.25) and we still have 0.05 remaining. Carry the integer over again by multiplying by 2 and adding the number at the top (0).

Step 3
Binary Number: 0 1 0
Powers of 2: 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.000976563
Remainder: 0.30 0.05 0.05
Integer: 0
(/2)
1
(/4)
2
(/8)

The integer row gets another two shifts to the right by multiplying by 2 each time since each column represents the next power of 2 down (1/2 -> 1/4 -> 1/8).

Step 4 and Step 5
Binary Number: 0 1 0 0 1
Powers of 2: 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.000976563
Remainder: 0.30 0.05 0.05 0.05 0.01875
Integer: 0
(/2)
1
(/4)
2
(/8)
4
(/16)
9
(/32)

Step 4 is multiplying by 2 and adding 0 again, Step 5 is the next 1.

Steps 6-10
Binary Number: 0 1 0 0 1 1 0 0 1 1
Powers of 2: 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.000976563
Remainder: 0.30 0.05 0.05 0.05 0.01875 0.003125 0.003125 0.003125 0.001171875 0.000195312
Integer: 0
(/2)
1
(/4)
2
(/8)
4
(/16)
9
(/32)
19
(/64)
38
(/128)
76
(/256)
153
(/512)
307
(/1024)

, but this will explain why a 15% haste stat will actually give you something like 14.996% haste.


256 and 1024 Numbers

There's some reduction in precision when converting to a smaller data type. Smaller percentages start at multiples of 10/1024, but it's a software limitation. It's not that the programmers are lazy, but that you wouldn't be programming the exact number unless you were writing in the assembly language. The conversion can also be done differently depending on the math library used: in the DirectX Math library its conversion is done by multiplying the decimal by 255 and rounding.

Percentage /256 Integer /1024 Integer
1% 2 10
2% 5 20
3% 7 30
4% 10 40
5% 12 51
6% 15 61
7% 17 71
8% 20 81
9% 23 92
10% 25 102
11% 28 112
12% 30 122
13% 33 133
14% 35 143
15% 38 153
16% 40 163
17% 43 174
18% 46 184
19% 48 194
20% 51 204
21% 53 215
22% 56 225
23% 58 235
24% 61 245
25% 64 256

Rollover

With these numbers, 0% and 100% are represented by the same number. When the data holds 0-1023, 1023 plus 1 rolls the counter back to 0. There have been instances of numbers rolling over. This is now fixed, but obtaining 100% dual wield used to reset your delay as if you had 0 dual wield.

Data limits

Power of 2 Feature Other details
4 PDIF Monsters have a PDIF limit of 4.0, even if they crit.
8 Auction You can have 0-7 items in the auction system at a time.
8 Mog Wardrobe Number of mog wardrobes was increased from 4 to 8.
8 Stat Ranks Basic ranks are A-G, with an extra NM-exclusive rank?
8 Melee Attacks Limit to the number of hits per melee attack.
16 Combat Skills There are 16 different weapon types, including a pet damage type and damage with no type.
128 Levels Subjobs are limited to levels 0-127. Monsters above level 127 will have a level 127 subjob.
1024 Spells Total number of spells in a dat file. Only a few spots left, sorry Blue Magic and Trust Magic, no more room for you.

Related Links