연산자

1. 산술 연산자

구분연산자연산피연산자 타입
사칙 연산과 나머지+덧셈정수, 실수, 복소수, 문자열
-뺄셈정수, 실수, 복소수
*곱셈정수, 실수, 복소수
/나눗셈정수, 실수, 복소수
%나머지정수, 실수, 복소수
비트 연산&AND 비트연산정수
|OR비트 연산정수
^XOR비트 연산정수
&^비트 클리어정수
시프트 연산«왼쪽 시프트정수 « 양의 정수
»오른쪽 시프트정수 » 양의 정수

산술 연산은 다른 언어의 연산과 별로 다를 것이 없으며 go는 강타입 언어이기 때문에 반드시 피연산자들끼리의 타입이 같아야만 에러가 발생하지 않는다.


1) ^

a := uint8(1)
fmt.Printf("%08b",a)  //00000001
fmt.Printf("%08b",^a) //11111110

비트 연산중에 **^(XOR)**은 혼자쓰이면 비트 반전(1의 보수,NOT)으로 사용될 수 있다.


2) &^

a := uint8(255)
fmt.Printf("%08b \n",a) //11111111
fmt.Printf("%08b \n",a&^2) //11111101
fmt.Printf("%08b \n",a&^8) //11110111

&^ 연산은 비트 클리어연산으로 우측 피연산자를 ^(NOT) 으로 사용된 후 양쪽 피연산자에 대해 & 를 수행한 것으로 왼쪽 피연산자 비트에서 오른족 피연산자의 1의 값을 갖는 위치의 비트를 0으로 바꾸고 싶을 때 사용한다.


3) 시프트 연산

a := uint8(1)                     //00000001
b := int8(-1)                     //11111111
fmt.Printf("%08b \n",a<<4)        //00010000
fmt.Printf("%08b \n",uint8(b<<4)) //11110000
fmt.Printf("%08b \n",a>>1)        //00000000
fmt.Printf("%08b \n",uint8(b>>4)) //11111111

« 연산은 비트를 왼쪽으로 밀고 새로 채우는 비트는 무조건 0으로 채운다.

» 연산은 왼쪽피연산자의 부호에 따라 새로 채우는 비트의 값이 달라지며, 부호가 없는 정수라면 0, 음수라면 1로 채워진다.



2. 비교 연산

연산자설명
==같다
!=같지 않다
<작다
>크다
<=작거나 같다
>=크거나 같다

1) 실수 비교

a := 0.1
b := 0.2
c := 0.3
d := a+b

fmt.Println(c == d)   //false
fmt.Println("c : "+ strconv.FormatFloat(c,'f',-1,64)) //0.3
fmt.Println("d : "+ strconv.FormatFloat(d,'f',-1,64)) //0.30000000000000004

실수 계산시 부동소수점 방식은 오차가 발생할 수 있어 원하는 결과값을 도출해내지 못할 수 있기때문에 특정 범위까지의 오차를 지정해 무시하거나 패키지를 이용해서 정밀하게 연산을 수행하는 방법을 택해야 한다.


특정 범위 지정

const floatRange = 0.000001

func equal(a,b float64) bool{
    if a>b{
        if a-b > floatRange{
          return false;
        }
        return true;
    }else{
        if b-a > floatRange {
            return false;
        }
        return true;
    }
}

func main() {
    a := 0.1
    b := 0.2
    c := 0.3
    d := a+b

    fmt.Println(equal(c,d)) //true
}

오차를 허용할 범위를 상수로 선언을 한 후에 별도의 함수를 만들어 비교하는 방법을 이용할 수 있다.


Float객체

import (
    "fmt"
    "math/big"
)


func main() {
    a, _ := new(big.Float).SetString("0.1")
    b,_ := new(big.Float).SetString("0.2")
    c,_ := new(big.Float).SetString("0.3")
    d := new(big.Float).Add(a,b)

    fmt.Println(c == d)   //false
    fmt.Println(c.Cmp(d)) //0
}

big의 Float객체를 이용해서 소수를 표현하고 산술/비교연산을 수행하면 정밀한 오차까지 계산을 수행할 수 있으며, 해당 변수는 객체이기 때문에 == 연산은 false가 되고 값 비교는 Cmp() 메서드를 이용하면 되고 Java의 compareTo와 비슷하게 주체가 크면 1, 작으면 -1, 같으면 0을 반환한다.



3. 논리 연산

종류연산자항 개수설명
논리&&다항 연산자양변 모두 true면 true
| |다항 연산자양변 중 하나라도 true면 true
!단항 연산자true이면 false, false이면 true

func setD(d *int) int{
    *d= 3
    return *d
}

func main() {
    c := 3
    d := 0

    fmt.Println( true || setD(&d) == c)  //true
    fmt.Println(d)    //0

    fmt.Println( false || setD(&d) == c)  //true
    fmt.Println(d)    //3
}

논리 연산시 단락 회로 평가(쇼트 서킷) 로 왼쪽 피연산자가 true나 false조건이 만족한다면 오른쪽 피연산자를 참조하지 않고 바로 return하게 된다.

예를 들어 && 연산을 수행할때 왼쪽 피연산자가 false라면 오른쪽 피연산자의 결과에 상관없이 false를, || 연산은 왼쪽이 true라면 바로 true를 리턴하게 된다.



4. 대입 연산

var a int
var b int
a = b = 1   //error

/*success*/
a = 1
b = 1

대입 연산은 다른 언어들과 거의 동일하며 복합 대입연산자도 지원을 하지만 특정 문법의 제약이 강해 위와 같은 방법으로 대입은 불가능하다.





Reference

『Tucker의 Go 언어 프로그래밍』 스터디 요약 노트

Tags :

Related Posts

@OneToMany 관계시 발생한 에러

@OneToMany 관계시 발생한 에러

  • Error
  • 2021년 4월 11일

JPA의 구현체인 hiberante를 이용해서 엔티티간의 상속관계를 설정하고 처음 사용해보는데 발생한 에러인 A collection with cascade=“all-delete-orphan” was no longer referenced by the owning entity instance 문제 해결한 방법을 기록하려고 한다. User의 엔티티와 Customer엔티티간의 1:N 양방향 연관관계를 맺기 위해 User에는 @OneToMany를 Customer에는 @ManyToOn...

Read More
List를 Array로 Array를 List로 변환

List를 Array로 Array를 List로 변환

  • Java
  • 2021년 5월 27일

List와 Array간의 변환은 기본적으로 for문을 이용하여 하나하나 바꾸어주면 변환이 가능하다. 하지만 for이 아닌 stream API를 이용해서 더 간편하게 바꿀 수 있는 방법을 정리한다. 1. List에서 Array로 변환 1) List -> Object[] List<Integer> integerList = new ArrayList<>(); List<String> stringList = new ArrayList<>(); Integer[] integerArr = integerList.toArray(new Integer[integerList.size()]); String[] stringArr = stringList.toArray(new String[stringList.size()]); Object[] objectArr = integerList.toArray(); List에서 Wrapper객체배열로 바꾸는 것은 Li...

Read More
Spring 요청처리 내부구조

Spring 요청처리 내부구조

내가 이해하고 나중에 보기 위해서 정리하는 스프링 요청 처리 구조 내부 구조 요약 1. Tomcat (Servlet Container) 톰캣은 WAS로써 미들웨어역할을 하지만 아파치의 일부분 기능을 서비스(httpd(웹서비스 데몬) native 모듈 포함)하고있어 Web Server역할도 수행할 수 있다. 톰캣의 메인 기능으로 서블릿 컨테이너역할인데 이는 서블릿의 라이플 사이클을 관리하며 Disp...

Read More