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.

Reply via email to