On Friday, January 12, 2018 at 9:00:34 AM UTC-5, di...@veryhaha.com wrote: > > > > On Friday, January 12, 2018 at 5:11:10 AM UTC-5, Axel Wagner wrote: >> >> Hm, this thread has actually opened up a question I don't have a good >> answer to. >> >> On Fri, Jan 12, 2018 at 9:47 AM, <di...@veryhaha.com> wrote: >> >>> then can I say >>> an untyped rune literal/constant is representable int type for sure. >>> >> >> Yes, rune is an alias for int32 and int is specified to have at least the >> precision of an int32. >> >> >>> an untyped interger literal/constant is representable float64 type for >>> sure. >>> an untyped floating-point literal/constant is representable complex128 >>> type for sure. >>> >> >> Now, this is where I don't have a good answer. The answer to both of >> these is actually "no", but the compiler still allows it. >> >> For example, the integer constant (1<<54)+1 is not representable as a >> float64, contradicting the first statement. >> Also, the floating-point constant math.Pi is not representable as a >> float64 and thus can't be represented by a complex128 either (as that has a >> float64 real part). >> In both cases, the compiler rounds to the nearest representable value, >> but does not complain. I tried reading in the spec why exactly, but so far >> I couldn't. >> >> Let's start with a constant declaration like this: >> const x = float64((1<<54)+1) >> * 1 and 54 are integer literals >> <https://golang.org/ref/spec#Integer_literals>, so they denote untyped >> integer constants. >> * That makes (1 << 54)+1 a constant expression >> <https://golang.org/ref/spec#Constant_expressions>, resulting in another >> untyped integer constant. >> * We then convert that to float64, creating a typed constant; I would >> argue, that in this case "The values of typed constants must always be >> accurately representable as values of the constant type." *should* apply >> (it's where the declaration would fail if, e.g., we'd use int32 instead), >> but doesn't, for some reason. I'm not sure why (there is a section in >> conversions <https://golang.org/ref/spec#Conversions> which specifies >> rounding for floating-point constants; but in this case, we have an >> integer-constant). >> >> Another way to do the same thing would be: >> const x float64 = (1<<54)+1 >> * Again, (1<<54)+1 is an untyped integer constant >> * This time, we are creating a typed constant declaration >> <https://golang.org/ref/spec#Constant_declarations>, though, requiring >> that "the expressions must be assignable to that type" >> * Assignability <https://golang.org/ref/spec#Assignability> of untyped >> constants requires, again, that the constant is representable as a T, where >> T in our case is float64. Which isn't the case, so, again, this *should* >> fail, IMO, but doesn't. >> >> Next, let's look at a declaration like >> const x = float64(math.Pi) >> * math.Pi is an untyped floating-point constant >> * The section on Conversions <https://golang.org/ref/spec#Conversions> >> allows >> a conversion of floating-point constants to a floating-point type, if the >> value is representable after rounding. I don't understand the qualification >> (because to me, rounding would seem to imply that the value is >> representable), but in any case, this would allow for the conversion to >> succeed and give the expected outcome. >> >> But if we instead look at >> const x float64 = math.Pi >> * math.Pi is an untyped floating-point constant >> * This time, we are not doing a conversion, but instead directly assign >> the value in a constant declaration. That *should* again require the >> value to be representable and thus fail. >> >> Notably, the conversion section also talks about non-constant conversions >> (and specifies rounding to precision for floats) >> >> >> Now, the rules, in practice, seem to be equivalent to >> 1) In the "conversion" section, replace "x is a floating-point constant" >> with "x is a non-complex numeric constant" >> 2) In various places about constants/constant expressions, replace >> "representable" with "convertible", allowing them to fall back to the >> rounding rule in the conversion section. >> >> But I might also overlook something blatantly obvious that someone more >> familiar with the spec can point out. >> >> >> In either case, in practice, it seems true that >> * You can always use an integer/rune-literal as a floating-point constant >> (potentially incurring rounding) >> * You can always use a floating-point literals as a complex constant >> (potentially incurring rounding) >> Note, however, that it doesn't matter *what* floating-point/complex >> constant it is. I.e. you can also assign any integer-literal to a float32 >> and any floating-point literal to a complex64 and the compiler will just >> round. There seems to be no way to statically assert that a literal is >> representable as a floating-point/complex type. >> > > Thanks for the info again. > > It looks not every integer literal can be used as float32 > > const N = 1 << 128 > const F float32 = N // constant 3.40282e+38 overflows float32 > > But I haven't found an integer literal which can't be used as float64. >
Ah, I found an integer literal which can't be used as float64 const N = 1e1000 const F float64 = N // constant 1e+1000 overflows float64 So my assumptions are not correct. Thank all for the various information. > >> >> >>> >>> On Friday, January 12, 2018 at 2:42:20 AM UTC-5, Axel Wagner wrote: >>>> >>>> What do you mean by "potential type"? There is no such concept. >>>> >>>> The spec <https://golang.org/ref/spec#Constants> is pretty clear, on >>>> the subject, IMO. There is also this blog post >>>> <https://blog.golang.org/constants>. >>>> >>>> The gist is: There are boolean, rune, integer, floating, complex and >>>> string constants. Each of them can be used as values for different sets of >>>> types - for boolean/string constants, the underlying types must be >>>> bool/string. For numeric types, the value (roughly, details in the links >>>> above) must be representable in the target type. This takes care of all >>>> the >>>> clearly typed places a constant can appear (e.g. in an expression, a typed >>>> const/var-declaration, a conversion…). Where that's not possible (e.g. an >>>> untyped const/var-declaration, short variable declaration, when used in an >>>> interface{} in an expression…) the default type of the literal (bool, >>>> rune, >>>> int, float64, complex128 and string respectively) is assumed. >>>> >>>> What that means is, that you can use any rune/integer/float/complex >>>> literal in any place where any numeric value is used (so anything with >>>> underlying type {u,}int*, rune, float{32,64}, complex{64,128}, uintptr)* >>>> as long as its value can be represented in the target type*. So, for >>>> example this is legal <https://play.golang.org/p/ujaq428Ls6J>, but this >>>> is not <https://play.golang.org/p/Eb1ddSuCmyd>. >>>> >>>> On Fri, Jan 12, 2018 at 8:07 AM, <di...@veryhaha.com> wrote: >>>> >>>>> or >>>>> an untype literal who has a *rune* potential type must also has an >>>>> *int* potential type. >>>>> an untype literal who has an *int* potential type must also has a >>>>> *float64* potential type. >>>>> an untype literal who has a *float64* potential type must also has a >>>>> *complex128* potential type. >>>>> >>>>> >>>>> On Friday, January 12, 2018 at 1:34:08 AM UTC-5, di...@veryhaha.com >>>>> wrote: >>>>>> >>>>>> An untyped rune literal/constant must have a popential int type. >>>>>> An untyped interger literal/constant must have a popential float64 >>>>>> type. >>>>>> An untyped floating-point literal/constant must have a popential >>>>>> complex128 type. >>>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "golang-nuts" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to golang-nuts...@googlegroups.com. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.