Ruby 2.4 병합 Fixnum
&Bignum
동일한 클래스로 (Integer
) 그래서 지금이 Ruby의 다양한 숫자 유형을 검토하기에 좋은 시간이라고 생각합니다!
이것이 우리가 이 게시물에서 이야기할 내용입니다 🙂
숫자 유형 개요
Ruby에서 모든 숫자 관련 클래스의 클래스 계층 구조를 살펴보는 것으로 시작하겠습니다.
숫자 정수 Fixnum Bignum Float Complex Rational BigDecimal(표준 라이브러리)
보시다시피 Numeric
class는 모든 number 클래스의 부모입니다. ancestors
를 사용할 수 있음을 기억하십시오. 모든 클래스의 상위 클래스를 검색하는 메서드입니다.
예 :
Fixnum.ancestors - Fixnum.included_modules[Fixnum, Integer, Numeric, Object, BasicObject]
이제 이러한 클래스를 테이블 형식으로 살펴보겠습니다.
클래스 | 설명 | 예 |
---|---|---|
정수 | Fixnum 의 상위 클래스 &Bignum | 1 |
수정 번호 | OS 정수 유형(32 또는 64비트)에 맞는 정수 | 1 |
빅넘 | 더 큰 숫자에 사용 | 111111111111 |
플로트 | 정확하지 않은 십진수 | 5.0 |
복잡함 | 허수와 수학 문제에 사용 | (1+0i) |
합리적 | 분수를 나타내는 데 사용 | (2/3) |
BigDecimal | 완벽한 정밀도 십진수 | 3.0 |
부동 정밀도
Float
Ruby의 클래스는 공식 Ruby 문서에서 "정확하지 않음"으로 설명되어 있습니다.
그 이유는 무엇입니까?
예를 보여드리겠습니다 :
0.2 + 0.1 ==0.3# 거짓
이것이 왜 거짓입니까?
0.2 + 0.1
의 결과를 봅시다. :
0.30000000000000004
정확히! 이것이 바로 우리가 부정확성을 의미하는 것입니다.
이것은 float가 저장되는 방식 때문에 발생합니다. 항상 정확한 십진수가 필요한 경우 BigDecimal
을 사용할 수 있습니다. 수업.
Float 대 BigDecimal
BigDecimal은 임의의 정밀도 십진수를 제공하는 클래스입니다.
예 :
'bigdecimal'BigDecimal("0.2") + BigDecimal("0.1") ==0.3# true 필요
항상 BigDecimal
을 사용하지 않는 이유 그 다음에? 훨씬 느리기 때문입니다!
다음은 벤치마크입니다. :
계산하기 ---------------------------------- bigdecimal 21.559k i/100ms float 79.336k i/ 100ms-------------------------------------------------- bigdecimal 311.721k(± 7.4%) i/s - 1.552M float 3.817M(±11.7%) i/s - 18.803M비교:float:3817207.2 i/s bigdecimal:311721.2 i/s -x 더 느림
BigDecimal
Float
보다 12배 느립니다. , 그리고 이것이 기본값이 아닌 이유입니다 🙂픽스넘 대 빅넘
이 섹션에서는
Fixnum
간의 차이점을 살펴보고자 합니다. 및Bignum
루비 2.4 이전.몇 가지 코드부터 시작하겠습니다. :
1.class# Fixnum100000000000.class# 빅넘Ruby는 올바른 클래스를 생성하고 자동으로
<블록 인용>Fixnum
을 승격합니다.Bignum
으로 필요할 때.참고 :
Bignum
을 얻으려면 더 큰 숫자가 필요할 수 있습니다. 64비트 Ruby 인터프리터가 있는 경우 개체.왜 다른 수업이 필요한가요? 대답은 더 큰 숫자로 작업하려면 다른 구현이 필요하고 큰 숫자로 작업하는 것이 더 느리기 때문에
Float
와 비슷한 상황이 발생한다는 것입니다. 대BigDecimal
.픽스넘의 특수 속성
Fixnum
클래스에도 몇 가지 특별한 속성이 있습니다. 예를 들어 개체 ID는 공식을 사용하여 계산됩니다.1.object_id# 320.object_id# 41공식은 다음과 같습니다.
(number * 2) + 1
.그러나
Fixnum
을 사용할 때 이것에 더 많은 것이 있습니다. 생성되는 객체가 전혀 없습니다.Fixnum
에 저장할 데이터가 없습니다. , 값이 개체 ID 자체에서 파생되기 때문입니다.이것은 구현 세부 사항일 뿐이지만 알고 보면 재미있을 것 같아요 🙂
MRI(Matz의 Ruby Interpreter)는 다음 두 매크로를 사용하여 값과 객체 ID 사이를 변환합니다.
INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG))FIX2LONG(x) ((long)RSHIFT((SIGNED_VALUE)(x),1))여기서 일어나는 일은 모든 비트를 왼쪽이나 오른쪽으로 이동하는 "비트 시프팅"이라고 합니다.
한 위치를 왼쪽으로 이동하는 것은 2를 곱하는 것과 동일하므로 공식이
(number * 2) + 1
입니다. . +1은FIXNUM_FLAG
에서 옵니다. .대조적으로,
Bignum
일반 클래스처럼 작동하고 일반 개체 ID를 사용합니다.111111111111111.object_id# 23885808이 모든 의미는
Fixnum
객체는 인터프리터 수준에서 작동하는 방식 면에서 기호에 더 가깝지만Bignum
개체가 문자열에 더 가깝습니다.2.4의 정수
Ruby 2.4부터 Fixnum 및 Bignum은 더 이상 사용되지 않지만 그 뒤에서는 여전히 동일한 방식으로 작동합니다.
Ruby는 자동으로 한 유형에서 다른 유형으로 전환합니다.
클래스 변경 없이 .
이는 작은
Integer
숫자는 여전히Fixnum
과 같은 방식으로 작동합니다. .요약
이 게시물에서는 Ruby에 존재하는 다양한 숫자 관련 클래스에 대해 배웠습니다.
float가 부정확하고
BigDecimal
을 사용할 수 있다는 것을 배웠습니다. 정확도가 성능보다 훨씬 더 중요하다면. 또한Fixnum
객체는 인터프리터 수준에서 특별하지만Bignum
s는 그냥 일반 개체입니다.이 게시물이 흥미롭다면 아래 양식에서 제 뉴스레터에 가입하는 것을 잊지 마세요 🙂