Number: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Text replacement - "\[https?\:\/\/en\.wikipedia\.org\/wiki\/([^ ]+) (.+)\]" to "{{Wikipedia|$1|$2}}")
(Started "Floating-point Precision" section)
Line 4: Line 4:


== Scripting ==
== Scripting ==
 
In [[SQF Syntax|SQF]], there are multiple accepted number formats.
In SQF, there are multiple accepted number formats.
However, all of them will result in the same {{ic|SCALAR}} ([[typeName]]) value type.
However, all of them will result in the same {{ic|SCALAR}} ([[typeName]]) value type.


The '''<span style="color: #008000;">largest positive</span>''' number that can be achieved is {{ic|3.4028235e38}} and the '''<span style="color: #800000;">largest negative</span>''' is {{ic|-3.4028235e38}}.<br>
The '''<span style="color: #008000;">largest positive</span>''' number that can be achieved is {{ic|3.4028235e38}} and the '''<span style="color: #800000;">largest negative</span>''' is {{ic|-3.4028235e38}}.<br>
Line 17: Line 16:


=== Decimal (Base 10) ===
=== Decimal (Base 10) ===
A decimal number is your normal {{ic|0.5}} syntax stuff with one extra: You may omit the initial pack of digits.
A decimal number is your normal {{ic|0.5}} syntax stuff with one extra: You may omit the initial pack of digits.


Line 41: Line 39:


=== Hexadecimal (Base 16) ===
=== Hexadecimal (Base 16) ===
In [[SQF Syntax|SQF]], {{Wikipedia|Hexadecimal|hexadecimal}} (also base 16, or hex) is a positional numeral system with a base of 16.  
In [[SQF Syntax|SQF]], {{Wikipedia|Hexadecimal|hexadecimal}} (also base 16, or hex) is a positional numeral system with a base of 16.  
They start either with {{ic|0x}} or with a single {{ic|$}}.
They start either with {{ic|0x}} or with a single {{ic|$}}.
Line 55: Line 52:


A regex catching these kind of numbers could look like this {{ic|<nowiki>((\$|0x)[0-9a-fA-F]+)\b</nowiki>}}
A regex catching these kind of numbers could look like this {{ic|<nowiki>((\$|0x)[0-9a-fA-F]+)\b</nowiki>}}


== Config ==
== Config ==
Unlike scripting, configs actually do allow for multiple number types (Integer, [[Float]], etc). They are properly stored with their corresponding type in mind.
Unlike scripting, configs actually do allow for multiple number types (Integer, [[Float]], etc). They are properly stored with their corresponding type in mind.
{{Feature | Informative | In a config, a [[Number]] can also mean a [[Boolean]]: in [[Description.ext]] for example, {{ic|disabledAI {{=}} 1;}} means [[true]].}}
{{Feature | Informative | In a config, a [[Number]] can also mean a [[Boolean]]: in [[Description.ext]] for example, {{ic|disabledAI {{=}} 1;}} means [[true]].}}
Line 64: Line 61:
class MyClass
class MyClass
{
{
myInt = 1; // integer;
myInt = 1; // integer
myFloat = 0.01; // float;
myFloat = 0.01; // float
};
};


// description.ext example
// description.ext example
disabledAI = 1; // boolean: 0 = false, anything else = true (usually 1)
disabledAI = 1; // boolean: 0 = false, everything else = true (usually 1)
</syntaxhighlight>
</syntaxhighlight>
== Floating-point Precision ==
{{Wiki|WIP}}
As mentioned above, every number in scripting is a ''floating-point number''. Because any given floating-point number can only consist of a finite amount of bits (a computer's memory is finite after all), there are gaps between floating-point numbers. However, humans are typically used to performing mathematical calculations on the set of ''real numbers'' (ℝ), and there are no gaps between real numbers; there is always another real number between two real numbers.<br>
This induces the following problem: There are real numbers that the computer does not have a binary representation for (and that it therefore can not work with) because there is no representation for these numbers in the specific floating-point format used by the computer. Of course, by extension, this also applies to the [[Real Virtuality]] Engine - there are real numbers that it does not have a representation for.
This issue is dealt with by rounding to the nearest number that can actually be represented as a floating-point number.
{| class="wikitable" style="margin: auto"
|-
! <var>n</var> ∈ ℝ !! <var>n</var> in {{arma3}}<br>(value of {{ic|n [[toFixed]] 20}})
|- style="background-color: lightgreen"
| 0 || 0.00000000000000000000
|- style="background-color: lightgreen"
| 1 || 1.00000000000000000000
|-
| 1.1 || 1.10000002384185790000
|- style="background-color: lightgreen"
| 2.5 || 2.50000000000000000000
|-
| 2.51 || 2.50999999046325680000
|}
Unfortunately, this rounding introduces a new problem in the form of unexpected, seemingly erroneous behaviour: Despite being entirely correct mathematically, the expression {{ic|0.3 [[+]] 0.4 [[==]] 0.7}} surprisingly returns [[false]] in {{arma3}}. <!-- TODO: Explain why... -->
To add to the confusion, {{ic|0.3 [[+]] 0.4}} will actually output <samp>0.7</samp> on the [[Arma 3: Debug Console|Debug Console]] or when used with commands like [[hint]] or [[systemChat]]. That is because numbers are rounded yet again when they are converted to [[String]] for the output. If this needs to be avoided, the [[toFixed]] command can be used to obtain the accurate value of a number.




[[Category: Data Types]]
[[Category: Data Types]]

Revision as of 22:15, 27 July 2021

A number is, depending on scope, either a single precision floating-point number (when talking about scripting) or a range of numerical types when talking about config context.


Scripting

In SQF, there are multiple accepted number formats. However, all of them will result in the same SCALAR (typeName) value type.

The largest positive number that can be achieved is 3.4028235e38 and the largest negative is -3.4028235e38.
It also is possible to generate positive or negative infinity values using either 1e39 (string representation: 1.#INF) or -1e39 (string representation: -1.#INF).

To check if a number is finite one can use the finite operator.

Regex to match all numbers in SQF is (((\$|0x)[0-9a-fA-F]+)|(\.[0-9]+))|(\b[0-9]+(\.[0-9]+|[eE][-+]?[0-9]+)?)\b
Due to technical limitations, the precision of floating-point numbers is limited. Please refer to IEEE 754 for more info about the technical details.

Decimal (Base 10)

A decimal number is your normal 0.5 syntax stuff with one extra: You may omit the initial pack of digits.

Some Examples would be:

  • 5.197
  • 0.47
  • 16.0
  • .8314
  • 12345

A regex catching these kind of numbers could look like this ((\.[0-9]+)|(\b[0-9]+(\.[0-9]+)?))\b

Scientific Notation

The Scientific Notation is a way of expressing numbers that are too big or too small to be conveniently written in decimal form.

It starts of like a normal decimal and then gets expressed by an E (Not case-sensitive, thus e is also valid) followed by an optional + or - sign and ends with a range of digits.

Some examples would be:

  • 1.23E4 ⇔ 1.23 ⋅ 104 ⇔ 12300
  • 5e-2 ⇔ 5 ⋅ 10-2 ⇔ 0.05

A regex catching these kind of numbers could look like this ([0-9]+.)?[0-9]+[eE][+-]?[0-9]+

Hexadecimal (Base 16)

In SQF, hexadecimal (also base 16, or hex) is a positional numeral system with a base of 16. They start either with 0x or with a single $.

This gets followed by one of the following characters: 0 1 2 3 4 5 6 7 8 9 A B C D E F.
Note that casing does not matter, thus both 0xa and 0xA are valid.

Some Examples would be:

  • 0xa5
  • $5C
  • $FFFFFF
  • 0x123ABC

A regex catching these kind of numbers could look like this ((\$|0x)[0-9a-fA-F]+)\b


Config

Unlike scripting, configs actually do allow for multiple number types (Integer, Float, etc). They are properly stored with their corresponding type in mind.

In a config, a Number can also mean a Boolean: in Description.ext for example, disabledAI = 1; means true.
class MyClass
{
	myInt = 1;		// integer
	myFloat = 0.01;	// float
};

// description.ext example
disabledAI = 1;		// boolean: 0 = false, everything else = true (usually 1)


Floating-point Precision

🏗
This article is a work in progress!

As mentioned above, every number in scripting is a floating-point number. Because any given floating-point number can only consist of a finite amount of bits (a computer's memory is finite after all), there are gaps between floating-point numbers. However, humans are typically used to performing mathematical calculations on the set of real numbers (ℝ), and there are no gaps between real numbers; there is always another real number between two real numbers.
This induces the following problem: There are real numbers that the computer does not have a binary representation for (and that it therefore can not work with) because there is no representation for these numbers in the specific floating-point format used by the computer. Of course, by extension, this also applies to the Real Virtuality Engine - there are real numbers that it does not have a representation for.

This issue is dealt with by rounding to the nearest number that can actually be represented as a floating-point number.

n ∈ ℝ n in Arma 3
(value of n toFixed 20)
0 0.00000000000000000000
1 1.00000000000000000000
1.1 1.10000002384185790000
2.5 2.50000000000000000000
2.51 2.50999999046325680000

Unfortunately, this rounding introduces a new problem in the form of unexpected, seemingly erroneous behaviour: Despite being entirely correct mathematically, the expression 0.3 + 0.4 == 0.7 surprisingly returns false in Arma 3.

To add to the confusion, 0.3 + 0.4 will actually output 0.7 on the Debug Console or when used with commands like hint or systemChat. That is because numbers are rounded yet again when they are converted to String for the output. If this needs to be avoided, the toFixed command can be used to obtain the accurate value of a number.