Variable size/Set: Difference between revisions
No edit summary |
|||
Line 407: | Line 407: | ||
{{omit from|M4}} |
{{omit from|M4}} |
||
{{omit from|Unlambda|Does not have variables.}} |
{{omit from|Unlambda|Does not have variables.}} |
||
{{omit from|Maxima}} |
Revision as of 16:08, 12 June 2012
You are encouraged to solve this task according to the task description, using any language you may know.
Demonstrate how to specify the minimum size of a variable or a data type.
Ada
<lang ada>type Response is (Yes, No); -- Definition of an enumeration type with two values for Response'Size use 1; -- Setting the size of Response to 1 bit, rather than the default single byte size</lang>
AutoHotkey
The documentation explains how the built-in function VarSetCapacity() may be used to do so.
BASIC
Numerical values and arrays generally are a fixed size. Strings are dynamically resized according to the data that they hold.
C
<lang c>#include <stdint.h>
int_least32_t foo;</lang>
Here foo is a signed integer with at least 32 bits. stdint.h also defines minimum-width types for at least 8, 16, 32, and 64 bits, as well as unsigned integer types.
C++
or
<lang Cpp>#include <boost/cstdint.hpp>
boost::int_least32_t foo;</lang>
D
In D, any variables of static array of zero length has a size of zero. But such data is useless, as no base type element can be accessed.
<lang d>typedef long[0] zeroLength ;
writefln(zeroLength.sizeof) ; // print 0</lang>
NOTE: a dynamic array variable's size is always 8 bytes, 4(32-bit) for length and 4 for a reference pointer of the actual storage somewhere in runtime memory.
The proper candidates of minimum size variable are empty structure, 1-byte size data type variable (include byte, ubyte, char and bool), and void, they all occupy 1 byte.
<lang d>byte b ;
ubyte ub ;
char c ;
bool t ;</lang>
bool is logically 1-bit size, but it actually occupy 1 byte.
void can't be declared alone, but void.sizeof gives 1.
An empty structure is logically zero size, but still occupy 1 byte.
<lang d>struct Empty { }
writefln(Empty.sizeof) ; // print 1</lang>
Fortran
Since Fortran 90 each intrinsic data type (INTEGER, REAL, COMPLEX, LOGICAL and CHARACTER) has a KIND parameter associated with it that can be used to set the required level of precision. The actual values which these KIND parameters can take are not specified in the standard and are implementation-dependent. In order to select an appropriate KIND value that is portable over different platforms we can use the intrinsic functions SELECTED_REAL_KIND and SELECTED_INT_KIND.
The syntax of these functions are as follows:-
selected_real_kind(P, R), where P is the required number of significant decimal digits and R is the required decimal exponent range. At least one argument must be present. The return value is the kind type parameter for real values with the given precision and/or range. A value of -1 is returned if P is out of range, a value of -2 is returned if R is out of range and a value of -3 is returned if both P and R are out of range.
selected_int_kind(R), where R is the required decimal exponent range. The return value is the kind type parameter for integer values n such that -10^R < n < 10^R. A value of -1 is returned if R is out of range.
<lang fortran>program setsize implicit none
integer, parameter :: p1 = 6 integer, parameter :: p2 = 12 integer, parameter :: r1 = 30 integer, parameter :: r2 = 1000 integer, parameter :: r3 = 2 integer, parameter :: r4 = 4 integer, parameter :: r5 = 8 integer, parameter :: r6 = 16 integer, parameter :: rprec1 = selected_real_kind(p1, r1) integer, parameter :: rprec2 = selected_real_kind(p2, r1) integer, parameter :: rprec3 = selected_real_kind(p2, r2) integer, parameter :: iprec1 = selected_int_kind(r3) integer, parameter :: iprec2 = selected_int_kind(r4) integer, parameter :: iprec3 = selected_int_kind(r5) integer, parameter :: iprec4 = selected_int_kind(r6) real(rprec1) :: n1 real(rprec2) :: n2 real(rprec3) :: n3 integer(iprec1) :: n4 integer(iprec2) :: n5 integer(iprec3) :: n6 integer(iprec4) :: n7 character(30) :: form form = "(a7, i11, i10, i6, i9, i8)" write(*, "(a)") "KIND NAME KIND NUMBER PRECISION RANGE " write(*, "(a)") " min set min set" write(*, "(a)") "______________________________________________________" write(*, form) "rprec1", kind(n1), p1, precision(n1), r1, range(n1) write(*, form) "rprec2", kind(n2), p2, precision(n2), r1, range(n2) write(*, form) "rprec3", kind(n3), p2, precision(n3), r2, range(n3) write(*,*) form = "(a7, i11, i25, i8)" write(*, form) "iprec1", kind(n4), r3, range(n4) write(*, form) "iprec2", kind(n5), r4, range(n5) write(*, form) "iprec3", kind(n6), r5, range(n6) write(*, form) "iprec4", kind(n7), r6, range(n7)
end program</lang> Output
KIND NAME KIND NUMBER PRECISION RANGE min set min set ______________________________________________________ rprec1 1 6 6 30 37 rprec2 2 12 15 30 307 rprec3 3 12 18 1000 4931 iprec1 1 2 2 iprec2 2 4 4 iprec3 3 8 9 iprec4 4 16 18
Go
For task interpretation this follows the spirit of the Ada example included by the task author. In it, an enumeration type is defined from enumeration values, then a storage size--smaller than the default--is specified for the type. A similar situation exists within Go. Defining types from values is called duck-typing, and the situation where a type smaller than the default can be specified exists when a variable is duck-typed from a numeric literal. <lang go>package main
import (
"fmt" "unsafe"
)
func main() {
i := 5 // default type is int r := '5' // default type is rune (which is int32) f := 5. // default type is float64 c := 5i // default type is complex128 fmt.Println("i:", unsafe.Sizeof(i), "bytes") fmt.Println("r:", unsafe.Sizeof(r), "bytes") fmt.Println("f:", unsafe.Sizeof(f), "bytes") fmt.Println("c:", unsafe.Sizeof(c), "bytes") iMin := int8(5) rMin := byte('5') fMin := float32(5.) cMin := complex64(5i) fmt.Println("iMin:", unsafe.Sizeof(iMin), "bytes") fmt.Println("rMin:", unsafe.Sizeof(rMin), "bytes") fmt.Println("fMin:", unsafe.Sizeof(fMin), "bytes") fmt.Println("cMin:", unsafe.Sizeof(cMin), "bytes")
}</lang> Output:
i: 4 bytes r: 4 bytes f: 8 bytes c: 16 bytes iMin: 1 bytes rMin: 1 bytes fMin: 4 bytes cMin: 8 bytes
Icon and Unicon
Icon and Unicon values are self-descriptive types subject to automatic garbage collection. As a result the opportunities for setting the sizes of the variables are limited.
- strings are always variable in length with some fixed overhead
- csets are a fixed size
- tables and sets are variable in size and start empty
- integers and reals are fixed sizes
- records are a fized size
- co-expressions vary in size based on the environment when they are created
- file, window, and procedure references are all fixed in size
- lists can be specified with a minimum size (see below):
<lang Icon> L := list(10) # 10 element list </lang>
J
<lang J>v=: </lang>
Here, v is specified to have a minimum size. In this case, the minimum size of the content is zero, though the size of the representation is somewhat larger.
Mathematica
Mathematica stores variables in symbols : e.g. variable 'A' containing integer 0 requires 24 bytes under Windows.
Modula-3
<lang modula3>TYPE UByte = BITS 8 FOR [0..255];</lang> Note that this only works for records, arrays, and objects. Also note that the size in bits must be large enough to hold the entire range (in this case, 8 bits is the correct amount for the range 0 to 255) or the compiler will error.
ooRexx
ooRexx variables are all references to object instances, so the variables themselves have no settable or gettable size.
PARI/GP
<lang parigp>default(precision, 1000)</lang> Alternately, in the gp interpreter, <lang parigp>\p 1000</lang>
Pascal
Ordinal and floating point types of FreePascal are listed here: [[1]] and here: [[2]] <lang pascal>var
a: byte; // 1 byte b: word; // 2 byte c: cardinal; // 4 byte d: QWord; // 8 byte
x: real; // 4 byte y: double; // 8 byte</lang>
Perl
I suppose you could use vec() or similar to twiddle a single bit. The thing is, as soon as you store this in a variable, the SV (the underlying C implementation of the most simple data type) already takes a couple dozen of bytes.
In Perl, memory is readily and happily traded for expressiveness and ease of use.
PL/I
<lang PL/I> declare i fixed binary (7), /* occupies one byte */
j fixed binary (15), /* occupies two bytes */ k fixed binary (31), /* occupies 4 bytes */ l fixed binary (63); /* occupies 8 bytes */
declare d fixed decimal (1), /* occupies 1 byte */
e fixed decimal (3), /* occupies 2 bytes */ /* an so on ... */ f fixed decimal (15); /* occupies 8 bytes. */
declare b(16) bit (1) unaligned; /* occupies 2 bytes */ declare c(16) bit (1) aligned; /* occupies 16 bytes */
declare x float, /* occupies 4 bytes. */
y float (15), /* occupies 8 bytes. */ z float (18); /* occupies 10 bytes */
</lang>
PicoLisp
In PicoLisp, all variables have the same size (a single cell). But it is possible to create a data structure of a given minimal size with the 'need' function.
Python
For compatibility with the calling conventions of external C functions, the ctypes module has functions that map data types and sizes between Python and C:
ctypes type | C type | Python type |
---|---|---|
c_char | char | 1-character string |
c_wchar | wchar_t | 1-character unicode string |
c_byte | char | int/long |
c_ubyte | unsigned char | int/long |
c_short | short | int/long |
c_ushort | unsigned short | int/long |
c_int | int | int/long |
c_uint | unsigned int | int/long |
c_long | long | int/long |
c_ulong | unsigned long | int/long |
c_longlong | __int64 or long long | int/long |
c_ulonglong | unsigned __int64 or unsigned long long | int/long |
c_float | float | float |
c_double | double | float |
c_longdouble | long double | float |
c_char_p | char * (NUL terminated) | string or None |
c_wchar_p | wchar_t * (NUL terminated) | unicode or None |
c_void_p | void * | int/long or None |
REXX
In REXX, there are no minimums for variables holding character literals,
so you just simply character strings to REXX variables.
However, to insure that REXX can store numbers with a minimum size,
the
NUMERIC DIGITS nnn
instruction can be used.
The default is 9 digits (accuracy).
There's effectively is no limit for the precision [or length] for REXX numbers (except for memory).
<lang rexx>
numeric digits 100
abc=12345678901111111112222222222333333333344444444445555555555.66
</lang>
Tcl
In Tcl, most values are (Unicode) strings. Their size is measured in characters, and the minimum size of a string is of course 0. However, one can arrange, via write traces, that the value of a variable is reformatted to bigger size. Examples, from an interactive tclsh session: <lang Tcl>% proc format_trace {fmt _var el op} {upvar 1 $_var v; set v [format $fmt $v]}
% trace var foo w {format_trace %10s} % puts "/[set foo bar]/" / bar/
% trace var grill w {format_trace %-10s} % puts "/[set grill bar]/" /bar /</lang> ..or limit its size to a certain length: <lang Tcl>% proc range_trace {n _var el op} {upvar 1 $_var v; set v [string range $v 0 [incr n -1]]}
% trace var baz w {range_trace 2} % set baz Frankfurt Fr</lang>
Ursala
There is no way to set the minimum size of natural, integer, or rational numbers, but no need because they all have unlimited precision.
For (mpfr format) arbitrary precision floating point numbers, there are several mechanisms for setting the minimum precision, although not the exact amount of real memory used.
- If it's initialized from a literal constant, the compiler infers the intended precision from the number of digits in the constant (or 160 bits, whichever is greater).
- The library function
mpfr..grow(x,n)
returns a copy ofx
with its precision increased byn
bits (padded with zeros). - The library function
mpfr..shrink(x,n)
returns a copy ofx
with its precision reduced byn
bits, or toMPFR_PREC_MIN
, whichever is greater. - Library functions such as
mpfr..pi
andmpfr..const_catalan
take a natural number specifying the precision as an argument and return a constant with at least that precision. - If two numbers of unequal precision are combined using any binary operation from the mpfr library, the result is computed and allocated using the greater precision of the two.
The last feature eliminates the need for explicitly setting the precision of numbers having exact representations, albeit contrary to the convention in physical sciences. <lang Ursala>p = mpfr..pi 200 # 200 bits of precision
x = mpfr..grow(1.0E+0,1000) # 160 default precision, grown to 1160
y = mpfr..shrink(1.0+0,40) # 160 default shrunk to 120
z = mpfr..add(p,y) # inherits 200 bits of precision
a = # 180 bits (not the default 160) because of more digits in the constant
1.00000000000000000000000000000000000000000000000000000E0</lang>
ZX Spectrum Basic
<lang basic>10 DIM a$(10): REM This array will be 10 characters long 20 DIM b(10): REM this will hold a set of numbers. The fixed number of bytes per number is implementation specific 30 LET c=5: REM this is a single numerical value of fixed size</lang>
- Programming Tasks
- Type System
- Ada
- AutoHotkey
- BASIC
- C
- C++
- D
- Fortran
- Go
- Icon
- Unicon
- J
- Mathematica
- Modula-3
- OoRexx
- PARI/GP
- Pascal
- Perl
- PL/I
- PicoLisp
- Python
- REXX
- Tcl
- Ursala
- ZX Spectrum Basic
- AWK/Omit
- E/Omit
- Gnuplot/Omit
- Groovy/Omit
- J/Omit
- Java/Omit
- JavaScript/Omit
- LaTeX/Omit
- Make/Omit
- PlainTeX/Omit
- PureBasic/Omit
- Ruby/Omit
- TI-83 BASIC/Omit
- TI-89 BASIC/Omit
- XSLT/Omit
- M4/Omit
- Unlambda/Omit
- Maxima/Omit