1
0
mirror of https://github.com/golang/go synced 2024-11-21 15:54:43 -07:00

go spec: remove float, complex in favor of float64 and complex128

The default float type is not very useful but for the most basic applications.
For instance, as it is now, using the math package requires conversions for float
variables (the arguments for math functions are usually float64). Typical real
applications tend to specify the floating point precision required.

This proposal removes the predeclared types float and complex. Variable declarations
without type specification but with constant floating point or complex initializer
expressions will assume the type float64 or complex128 respectively.

The predeclared function cmplx is renamed to complex.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/3423041
This commit is contained in:
Robert Griesemer 2011-01-19 23:07:21 -05:00 committed by Russ Cox
parent 50f384824e
commit b94c0d2a77

View File

@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification --> <!-- title The Go Programming Language Specification -->
<!-- subtitle Version of January 13, 2011 --> <!-- subtitle Version of January 18, 2011 -->
<!-- <!--
TODO TODO
@ -11,7 +11,7 @@ TODO
(struct{T} vs struct {T T} vs struct {t T}) (struct{T} vs struct {T T} vs struct {t T})
[ ] need explicit language about the result type of operations [ ] need explicit language about the result type of operations
[ ] may want to have some examples for the types of shift operations [ ] may want to have some examples for the types of shift operations
[ ] should string(1<<s) and float(1<<s) be valid? [ ] should string(1<<s) and float32(1<<s) be valid?
[ ] should probably write something about evaluation order of statements even [ ] should probably write something about evaluation order of statements even
though obvious though obvious
[ ] review language on implicit dereferencing [ ] review language on implicit dereferencing
@ -531,7 +531,7 @@ the result value of some built-in functions such as
<code>cap</code> or <code>len</code> applied to <code>cap</code> or <code>len</code> applied to
<a href="#Length_and_capacity">some expressions</a>, <a href="#Length_and_capacity">some expressions</a>,
<code>real</code> and <code>imag</code> applied to a complex constant <code>real</code> and <code>imag</code> applied to a complex constant
and <code>cmplx</code> applied to numeric constants. and <code>complex</code> applied to numeric constants.
The boolean truth values are represented by the predeclared constants The boolean truth values are represented by the predeclared constants
<code>true</code> and <code>false</code>. The predeclared identifier <code>true</code> and <code>false</code>. The predeclared identifier
<a href="#Iota">iota</a> denotes an integer constant. <a href="#Iota">iota</a> denotes an integer constant.
@ -700,8 +700,6 @@ There is also a set of predeclared numeric types with implementation-specific si
<pre class="grammar"> <pre class="grammar">
uint either 32 or 64 bits uint either 32 or 64 bits
int same size as uint int same size as uint
float either 32 or 64 bits
complex real and imaginary parts have type float
uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value
</pre> </pre>
@ -871,8 +869,8 @@ struct {}
// A struct with 6 fields. // A struct with 6 fields.
struct { struct {
x, y int x, y int
u float u float32
_ float // padding _ float32 // padding
A *[]int A *[]int
F func() F func()
} }
@ -1007,10 +1005,10 @@ func()
func(x int) func(x int)
func() int func() int
func(prefix string, values ...int) func(prefix string, values ...int)
func(a, b int, z float) bool func(a, b int, z float32) bool
func(a, b int, z float) (bool) func(a, b int, z float32) (bool)
func(a, b int, z float, opt ...interface{}) (success bool) func(a, b int, z float64, opt ...interface{}) (success bool)
func(int, int, float) (float, *[]int) func(int, int, float64) (float64, *[]int)
func(n int) func(p *T) func(n int) func(p *T)
</pre> </pre>
@ -1146,7 +1144,7 @@ failure will cause a <a href="#Run_time_panics">run-time panic</a>.
<pre> <pre>
map [string] int map [string] int
map [*T] struct { x, y float } map [*T] struct { x, y float64 }
map [string] interface {} map [string] interface {}
</pre> </pre>
@ -1197,7 +1195,7 @@ A channel may be constrained only to send or only to receive by
<pre> <pre>
chan T // can be used to send and receive values of type T chan T // can be used to send and receive values of type T
chan&lt;- float // can only be used to send floats chan&lt;- float64 // can only be used to send float64s
&lt;-chan int // can only be used to receive ints &lt;-chan int // can only be used to receive ints
</pre> </pre>
@ -1291,8 +1289,8 @@ type (
T1 []string T1 []string
T2 struct { a, b int } T2 struct { a, b int }
T3 struct { a, c int } T3 struct { a, c int }
T4 func(int, float) *T0 T4 func(int, float64) *T0
T5 func(x int, y float) *[]string T5 func(x int, y float64) *[]string
) )
</pre> </pre>
@ -1304,13 +1302,13 @@ these types are identical:
T0 and T0 T0 and T0
[]int and []int []int and []int
struct { a, b *T5 } and struct { a, b *T5 } struct { a, b *T5 } and struct { a, b *T5 }
func(x int, y float) *[]string and func(int, float) (result *[]string) func(x int, y float64) *[]string and func(int, float64) (result *[]string)
</pre> </pre>
<p> <p>
<code>T0</code> and <code>T1</code> are different because they are named types <code>T0</code> and <code>T1</code> are different because they are named types
with distinct declarations; <code>func(int, float) *T0</code> and with distinct declarations; <code>func(int, float64) *T0</code> and
<code>func(x int, y float) *[]string</code> are different because <code>T0</code> <code>func(x int, y float64) *[]string</code> are different because <code>T0</code>
is different from <code>[]string</code>. is different from <code>[]string</code>.
</p> </p>
@ -1483,7 +1481,7 @@ Basic types:
int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64
Architecture-specific convenience types: Architecture-specific convenience types:
complex float int uint uintptr int uint uintptr
Constants: Constants:
true false iota true false iota
@ -1492,7 +1490,7 @@ Zero value:
nil nil
Functions: Functions:
append cap close closed cmplx copy imag len append cap close closed complex copy imag len
make new panic print println real recover make new panic print println real recover
</pre> </pre>
@ -1561,7 +1559,7 @@ const (
eof = -1 // untyped integer constant eof = -1 // untyped integer constant
) )
const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo", untyped integer and string constants const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo", untyped integer and string constants
const u, v float = 0, 3 // u = 0.0, v = 3.0 const u, v float32 = 0, 3 // u = 0.0, v = 3.0
</pre> </pre>
<p> <p>
@ -1614,9 +1612,9 @@ const (
) )
const ( const (
u = iota * 42 // u == 0 (untyped integer constant) u = iota * 42 // u == 0 (untyped integer constant)
v float = iota * 42 // v == 42.0 (float constant) v float64 = iota * 42 // v == 42.0 (float64 constant)
w = iota * 42 // w == 84 (untyped integer constant) w = iota * 42 // w == 84 (untyped integer constant)
) )
const x = iota // x == 0 (iota has been reset) const x = iota // x == 0 (iota has been reset)
@ -1736,9 +1734,9 @@ VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList
<pre> <pre>
var i int var i int
var U, V, W float var U, V, W float64
var k = 0 var k = 0
var x, y float = -1, -2 var x, y float32 = -1, -2
var ( var (
i int i int
u, v, s = 2.0, 3.0, "bar" u, v, s = 2.0, 3.0, "bar"
@ -1763,7 +1761,7 @@ of the expression list.
<p> <p>
If the type is absent and the corresponding expression evaluates to an If the type is absent and the corresponding expression evaluates to an
untyped <a href="#Constants">constant</a>, the type of the declared variable untyped <a href="#Constants">constant</a>, the type of the declared variable
is <code>bool</code>, <code>int</code>, <code>float</code>, or <code>string</code> is <code>bool</code>, <code>int</code>, <code>float64</code>, or <code>string</code>
respectively, depending on whether the value is a boolean, integer, respectively, depending on whether the value is a boolean, integer,
floating-point, or string constant: floating-point, or string constant:
</p> </p>
@ -1771,7 +1769,7 @@ floating-point, or string constant:
<pre> <pre>
var b = true // t has type bool var b = true // t has type bool
var i = 0 // i has type int var i = 0 // i has type int
var f = 3.0 // f has type float var f = 3.0 // f has type float64
var s = "OMDB" // s has type string var s = "OMDB" // s has type string
</pre> </pre>
@ -2132,11 +2130,11 @@ primes := []int{2, 3, 5, 7, 9, 11, 13, 17, 19, 991}
// vowels[ch] is true if ch is a vowel // vowels[ch] is true if ch is a vowel
vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true} vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}
// the array [10]float{-1, 0, 0, 0, -0.1, -0.1, 0, 0, 0, -1} // the array [10]float32{-1, 0, 0, 0, -0.1, -0.1, 0, 0, 0, -1}
filter := [10]float{-1, 4: -0.1, -0.1, 9: -1} filter := [10]float32{-1, 4: -0.1, -0.1, 9: -1}
// frequencies in Hz for equal-tempered scale (A4 = 440Hz) // frequencies in Hz for equal-tempered scale (A4 = 440Hz)
noteFrequency := map[string]float{ noteFrequency := map[string]float32{
"C0": 16.35, "D0": 18.35, "E0": 20.60, "F0": 21.83, "C0": 16.35, "D0": 18.35, "E0": 20.60, "F0": 21.83,
"G0": 24.50, "A0": 27.50, "B0": 30.87, "G0": 24.50, "A0": 27.50, "B0": 30.87,
} }
@ -2155,7 +2153,7 @@ FunctionLit = FunctionType Body .
</pre> </pre>
<pre> <pre>
func(a, b int, z float) bool { return a*b &lt; int(z) } func(a, b int, z float64) bool { return a*b &lt; int(z) }
</pre> </pre>
<p> <p>
@ -2713,11 +2711,11 @@ the left operand alone.
<pre> <pre>
var s uint = 33 var s uint = 33
var i = 1&lt;&lt;s // 1 has type int var i = 1&lt;&lt;s // 1 has type int
var j = int32(1&lt;&lt;s) // 1 has type int32; j == 0 var j = int32(1&lt;&lt;s) // 1 has type int32; j == 0
var u = uint64(1&lt;&lt;s) // 1 has type uint64; u == 1&lt;&lt;33 var u = uint64(1&lt;&lt;s) // 1 has type uint64; u == 1&lt;&lt;33
var f = float(1&lt;&lt;s) // illegal: 1 has type float, cannot shift var f = float32(1&lt;&lt;s) // illegal: 1 has type float32, cannot shift
var g = float(1&lt;&lt;33) // legal; 1&lt;&lt;33 is a constant shift operation; g == 1&lt;&lt;33 var g = float32(1&lt;&lt;33) // legal; 1&lt;&lt;33 is a constant shift operation; g == 1&lt;&lt;33
</pre> </pre>
<h3 id="Operator_precedence">Operator precedence</h3> <h3 id="Operator_precedence">Operator precedence</h3>
@ -3128,8 +3126,8 @@ Consider a struct type <code>T</code> with two methods,
type T struct { type T struct {
a int a int
} }
func (tv T) Mv(a int) int { return 0 } // value receiver func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float) float { return 1 } // pointer receiver func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T var t T
</pre> </pre>
@ -3174,7 +3172,7 @@ yields a function value representing <code>Mp</code> with signature
</p> </p>
<pre> <pre>
func(tp *T, f float) float func(tp *T, f float32) float32
</pre> </pre>
<p> <p>
@ -3422,14 +3420,14 @@ result is an untyped complex constant.
Complex constants are always constructed from Complex constants are always constructed from
constant expressions involving imaginary constant expressions involving imaginary
literals or constants derived from them, or calls of the built-in function literals or constants derived from them, or calls of the built-in function
<a href="#Complex_numbers"><code>cmplx</code></a>. <a href="#Complex_numbers"><code>complex</code></a>.
</p> </p>
<pre> <pre>
const Σ = 1 - 0.707i const Σ = 1 - 0.707i
const Δ = Σ + 2.0e-4 - 1/1i const Δ = Σ + 2.0e-4 - 1/1i
const Φ = iota * 1i const Φ = iota * 1i
const iΓ = cmplx(0, Γ) const iΓ = complex(0, Γ)
</pre> </pre>
<p> <p>
@ -3680,8 +3678,8 @@ In assignments, each value must be
<a href="#Assignability">assignable</a> to the type of the <a href="#Assignability">assignable</a> to the type of the
operand to which it is assigned. If an untyped <a href="#Constants">constant</a> operand to which it is assigned. If an untyped <a href="#Constants">constant</a>
is assigned to a variable of interface type, the constant is <a href="#Conversions">converted</a> is assigned to a variable of interface type, the constant is <a href="#Conversions">converted</a>
to type <code>bool</code>, <code>int</code>, <code>float</code>, to type <code>bool</code>, <code>int</code>, <code>float64</code>,
<code>complex</code> or <code>string</code> <code>complex128</code> or <code>string</code>
respectively, depending on whether the value is a boolean, integer, floating-point, respectively, depending on whether the value is a boolean, integer, floating-point,
complex, or string constant. complex, or string constant.
</p> </p>
@ -3847,9 +3845,9 @@ case nil:
printString("x is nil") printString("x is nil")
case int: case int:
printInt(i) // i is an int printInt(i) // i is an int
case float: case float64:
printFloat(i) // i is a float printFloat64(i) // i is a float64
case func(int) float: case func(int) float64:
printFunction(i) // i is a function printFunction(i) // i is a function
case bool, string: case bool, string:
printString("type is bool or string") // i is an interface{} printString("type is bool or string") // i is an interface{}
@ -3868,9 +3866,9 @@ if v == nil {
printString("x is nil") printString("x is nil")
} else if i, is_int := v.(int); is_int { } else if i, is_int := v.(int); is_int {
printInt(i) // i is an int printInt(i) // i is an int
} else if i, is_float := v.(float); is_float { } else if i, is_float64 := v.(float64); is_float64 {
printFloat(i) // i is a float printFloat64(i) // i is a float64
} else if i, is_func := v.(func(int) float); is_func { } else if i, is_func := v.(func(int) float64); is_func {
printFunction(i) // i is a function printFunction(i) // i is a function
} else { } else {
i1, is_bool := v.(bool) i1, is_bool := v.(bool)
@ -4189,7 +4187,7 @@ func simple_f() int {
return 2 return 2
} }
func complex_f1() (re float, im float) { func complex_f1() (re float64, im float64) {
return -7.0, -4.0 return -7.0, -4.0
} }
</pre> </pre>
@ -4201,7 +4199,7 @@ func complex_f1() (re float, im float) {
"return" statement listing these variables, at which point the "return" statement listing these variables, at which point the
rules of the previous case apply. rules of the previous case apply.
<pre> <pre>
func complex_f2() (re float, im float) { func complex_f2() (re float64, im float64) {
return complex_f1() return complex_f1()
} }
</pre> </pre>
@ -4212,7 +4210,7 @@ func complex_f2() (re float, im float) {
and the function may assign values to them as necessary. and the function may assign values to them as necessary.
The "return" statement returns the values of these variables. The "return" statement returns the values of these variables.
<pre> <pre>
func complex_f3() (re float, im float) { func complex_f3() (re float64, im float64) {
re = 7.0 re = 7.0
im = 4.0 im = 4.0
return return
@ -4474,7 +4472,7 @@ For instance
</p> </p>
<pre> <pre>
type S struct { a int; b float } type S struct { a int; b float64 }
new(S) new(S)
</pre> </pre>
@ -4593,29 +4591,28 @@ n3 := copy(b, "Hello, World!") // n3 == 5, b == []byte("Hello")
<p> <p>
Three functions assemble and disassemble complex numbers. Three functions assemble and disassemble complex numbers.
The built-in function <code>cmplx</code> constructs a complex The built-in function <code>complex</code> constructs a complex
value from a floating-point real and imaginary part, while value from a floating-point real and imaginary part, while
<code>real</code> and <code>imag</code> <code>real</code> and <code>imag</code>
extract the real and imaginary parts of a complex value. extract the real and imaginary parts of a complex value.
</p> </p>
<pre class="grammar"> <pre class="grammar">
cmplx(realPart, imaginaryPart floatT) complexT complex(realPart, imaginaryPart floatT) complexT
real(complexT) floatT real(complexT) floatT
imag(complexT) floatT imag(complexT) floatT
</pre> </pre>
<p> <p>
The type of the arguments and return value correspond. The type of the arguments and return value correspond.
For <code>cmplx</code>, the two arguments must be of the same For <code>complex</code>, the two arguments must be of the same
floating-point type and the return type is the complex type floating-point type and the return type is the complex type
with the corresponding floating-point constituents: with the corresponding floating-point constituents:
<code>complex</code> for <code>float</code>,
<code>complex64</code> for <code>float32</code>, <code>complex64</code> for <code>float32</code>,
<code>complex128</code> for <code>float64</code>. <code>complex128</code> for <code>float64</code>.
The <code>real</code> and <code>imag</code> functions The <code>real</code> and <code>imag</code> functions
together form the inverse, so for a complex value <code>z</code>, together form the inverse, so for a complex value <code>z</code>,
<code>z</code> <code>==</code> <code>cmplx(real(z),</code> <code>imag(z))</code>. <code>z</code> <code>==</code> <code>complex(real(z),</code> <code>imag(z))</code>.
</p> </p>
<p> <p>
@ -4624,12 +4621,12 @@ value is a constant.
</p> </p>
<pre> <pre>
var a = cmplx(2, -2) // has type complex var a = complex(2, -2) // complex128
var b = cmplx(1.0, -1.4) // has type complex var b = complex(1.0, -1.4) // complex128
x := float32(math.Cos(math.Pi/2)) x := float32(math.Cos(math.Pi/2)) // float32
var c64 = cmplx(5, -x) // has type complex64 var c64 = complex(5, -x) // complex64
var im = imag(b) // has type float var im = imag(b) // float64
var rl = real(c64) // type float32 var rl = real(c64) // float32
</pre> </pre>
<h3 id="Handling_panics">Handling panics</h3> <h3 id="Handling_panics">Handling panics</h3>
@ -4984,7 +4981,7 @@ After
</p> </p>
<pre> <pre>
type T struct { i int; f float; next *T } type T struct { i int; f float64; next *T }
t := new(T) t := new(T)
</pre> </pre>