2013-07-04 5 views
4

Я определяю номер для ввода пользователем как var input float64, и я ввожу целое число, и я ожидаю получить ошибку, но получаю err = <nil>. Что мне не хватает?Почему нет ошибки несоответствия типа?

package main 

import (
    "fmt" 
) 

func main() { 
    var input float64 

    fmt.Print("Enter a number:") 

    n, err := fmt.Scanf("%f\n", &input) 

    fmt.Printf("err = %v\n", err) 

    if err != nil { 
     fmt.Printf("%v is not a float - exiting with error\n", input, err) 
     return 
    } 

    fmt.Printf("n is %v:", n) 
} 

Это выход:

C:\Go\src\play\exercise>go run exercise2.go 
Enter a number to take its square root: 1 
err = <nil> 
n is 1: 
+2

Вы знаете, что 1 является вполне допустимым числом с плавающей запятой? – fuz

+1

Нет, я не знал. Я думал, что числа с плавающей запятой должны быть записаны с десятичной точкой. То, как я думал, '1.0' не должно выдавать ошибку, но' 1' должно. Например, в книге Марка Саммерфилда о Go «числа с плавающей запятой пишутся с десятичной точкой ...» – Zeynel

+0

Я думаю, что то, что @FUZxxl пыталось сказать, состоит в том, что «1» отлично представляет собой число с плавающей запятой, а именно «1.0». Формат '% f' должен читать числа с плавающей запятой, содержащие десятичную точку. Это, вероятно, удобная вещь, потому что люди могут не захотеть набирать «1.0», если все нужно «1», но мне будет интересен более полный ответ, содержащий фактические данные;) – fresskoma

ответ

3

The Go Programming Language Specification

Conversions

Особые правила применяются к (непостоянные) преобразования между числовыми типов.

Преобразования между числовыми типами

Для превращения непостоянных числовых значений, следующие правила применяются:

  1. При преобразовании между целочисленными типами, если значением является знаковым целого числа, его знак растягивается до неявной бесконечной точности; в противном случае оно равно нулю. Затем он усекается, чтобы соответствовать размеру результата типа . Например, если v: = uint16 (0x10F0), то uint32 (int8 (v)) == 0xFFFFFFF0. Преобразование всегда дает действительное значение ; нет признаков переполнения.
  2. При преобразовании числа с плавающей запятой в целое число, фракция отбрасывается (усечение до нуля).
  3. При преобразовании целого числа или числа с плавающей запятой в тип с плавающей точкой или комплексное число другому сложному типу значение результата округляется до точности, заданной типом назначения . Например, значение переменной x типа float32 может быть сохранено с использованием дополнительной точности, отличной от 32-битового числа IEEE-754, но float32 (x) представляет результат округление значения x до 32-битной точности , Аналогично, x + 0,1 может использовать более 32 бит точности, но float32 (x + 0,1) этого не делает.

Во всех непостоянных преобразованиях, связанных с плавающей точкой или сложных значения, если тип результата не может представлять значение преобразования преуспевает, но значение результата зависит от конкретной реализации.

В Go вы можете преобразовать из целочисленного типа в тип с плавающей запятой. Поэтому нет причин не прощать.

Robustness principle

В вычислительной технике, принцип надежности является общим руководство по проектированию для программного обеспечения:

консервативны в том, что вы делаете, быть либералом в том, что вы принимаете от других (часто перефразировать, как «Будьте консервативны в том, что вы отправляете, будь то либеральным в том, что вы принимаете»).

Принцип также известен как закон Постела, после того, как интернет-пионер Джон Постел, который писал в начале спецификации передачи протокола управления, что: 1

реализации TCP должны следовать общему принципу устойчивости: быть консервативен в том, что вы делаете, будьте либеральными в том, что вы принимайте от других.

Другими словами, код, который посылает команды или данные на другие машины (или в другие программы на той же машине) должны соответствовать полностью спецификации, но код, который принимает входные данные должны принимать , не совместимого ввода до тех пор, поскольку смысл ясен.

+1

и просто для полноты здесь другая ссылка от спецификации golang: http://golang.org/ref/spec#Floating-point_literals – pkuderov

+1

Это фактически не отвечает на вопрос – ispilledthejava

1

Scanf сканирует текст для чтения со стандартного ввода, хранения последовательных разделенных пробелами значений в последовательных аргументов, как определяется форматом. Он возвращает количество успешно проверенных элементов.

Scanf возвращает количество прочитанных вещей. В этом случае n == 1, потому что ... вы ввели один токен, а затем новую строку. Предположительно, вы хотите получить значение input, а не n.

Смежные вопросы