Single
A 32-bit IEEE 754 single-precision floating-point number.
Syntax:
A Single variable is declared As Single, or by the type-declaration character ! after its name. DefSng makes Single the default type of the variables, parameters and functions whose names start with the letters in letterrange. A Single that is not given a value holds 0.
A Single has about 7 significant decimal digits. It takes half the space of a Double, which makes it suited to large arrays of approximate values and to API structures with 4-byte floating-point fields. It is not suited to money or to results that depend on small differences. The Variant subtype for a Single is vbSingle (4), and TypeName gives Single.
Storage and range
A Single is stored in 4 bytes: a sign bit, an 8-bit exponent and a 23-bit fraction. It holds values from -3.402823E38 to -1.401298E-45 and from 1.401298E-45 to 3.402823E38, and 0. It has the same size in a 32-bit and a 64-bit build. A value too small for the type becomes 0 with no error.
Most decimal fractions are not stored exactly, and a Single keeps only about 7 digits of them. 0.1 is stored as the nearest Single, which is about 0.100000001490116 when read as a Double, and 16,777,216 plus 1 is 16,777,216 again, because the type has no room for the 1.
Dim Ratio As Single
Dim Level!
Debug.Print Ratio ' 0
Debug.Print LenB(Ratio) ' 4
Debug.Print TypeName(Level) ' Single
Debug.Print VarType(Ratio) = vbSingle ' True
Ratio = 0.1
Debug.Print CDbl(Ratio) ' 0.100000001490116
Debug.Print CSng(1 / 3) ' 0.3333333
Dim Big As Single = 16777216
Debug.Print Big + 1 = Big ' True
Literals
A number with a decimal point or an exponent is a Double, so 1.5 and 1E3 are Double values. The suffix ! makes a literal a Single: 1.5!, 1E3! and 1!. A Single literal can be written with an exponent: 3.402823E+38!.
Debug.Print TypeName(1.5) ' Double
Debug.Print TypeName(1.5!) ' Single
Debug.Print TypeName(1!) ' Single
Debug.Print TypeName(1E3!) ' Single
Debug.Print 3.402823E+38! ' 3.402823E+38
Debug.Print 1.401298E-45! ' 1.401298E-45
Conversions
CSng converts an expression to a Single, and so does assigning one to a Single variable. A string is read as a number, so CSng("1.5") is 1.5, and True is -1. A string that is not a number raises error 13, Type mismatch.
A value too large for the type raises error 6, Overflow: CSng(1E+39) does, and so does assigning a Double that is too large, as Ratio = 1E+300.
Note
VB6 raises no error when a Double that is too large is assigned to a Single: the Single then holds infinity (1.#INF). twinBASIC raises error 6.
Dim Ratio As Single
Debug.Print CSng("1.5") ' 1.5
Debug.Print CSng(True) ' -1
On Error Resume Next
Ratio = 1E+39
Debug.Print Err.Number ' 6
Err.Clear
Ratio = CSng("abc")
Debug.Print Err.Number ' 13
Arithmetic and overflow
An operation on two Single values gives a Single, and so does a Single combined with a Byte, Integer or Boolean, with / as well as with +, - and *. Combined with a Long or LongLong it gives a Double, and so it does with a Double; with a Currency, a Currency under + and - and a Double under * and /; with a Decimal, a Decimal. ^ always gives a Double, and \ and Mod give a Long or a wider integer type. Result types and promotion has the full rules.
Dim Ratio As Single = 0.5
Debug.Print TypeName(Ratio + Ratio) ' Single
Debug.Print TypeName(Ratio * 2) ' Single
Debug.Print TypeName(Ratio / 2) ' Single
Debug.Print TypeName(Ratio + 1&) ' Double
Debug.Print TypeName(Ratio ^ 2) ' Double
Debug.Print TypeName(Ratio \ 1) ' Long
Debug.Print 0.1! + 0.2! = 0.3! ' True
Debug.Print 0.1 + 0.2 = 0.3 ' False
Warning BETA 1034
An addition, subtraction, multiplication or division whose result is a declared Single raises no error when the result overflows: the Single holds infinity (1.#INF) instead. VB6 raises error 6, Overflow. A division by zero stored in a declared Single raises no error either, whatever the types of its operands: the Single holds infinity, or NaN (-1.#IND) for zero divided by zero, where VB6 raises error 11, Division by zero, or error 6. Declare the variable Double where the error must be caught. Code compiled with LLVM has a similar defect for Double; see Language support.
A Variant holding a Single does not overflow: a result that does not fit becomes a Double.
Example
This example adds 0.1 to a Single ten times. The total prints as 1 but is not equal to 1, so a comparison of floating-point values should allow a small difference.
Dim Total As Single
Dim i As Long
For i = 1 To 10
Total = Total + 0.1!
Next
Debug.Print Total ' 1
Debug.Print Total = 1 ' False
Debug.Print Abs(Total - 1) < 0.000001 ' True
See Also
- Data Types – the summary of all fourteen intrinsic types
- Double, Currency, Decimal – the other non-integer types
- CSng function
- Deftype statement
- Result types and promotion – the type of an arithmetic result