프로토콜 버퍼에서 System.Decimal을 나타내는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/371604

문제

다음에서 이것 질문, 프로토콜 버퍼에서 System.Decimal 개체를 나타내는 가장 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책

Protobuf-Net은 이것을 단순히 당신을 위해 처리 할 것입니다. 그것은 유형의 속성을 벗어나고 전적으로 지원합니다. decimal. 직접적인 표현 방법이 없기 때문에 decimal 프로토에서는 (현재) 생성하지 않을 것입니다. decimal ".proto"파일의 속성이지만 일부 공통 유형 ( "bcl.decimal"또는 이와 유사한)을 인식하고 소수로 해석하는 것은 좋은 조정입니다.

그것을 대표하는 것에 관해서는 - 나는 a 토론 문서 Protobuf-Net Wiki 지역에서 이것 (현재는 의심되는 것)에; Protobuf-Net에는 이제 단순히 당신을 위해 그것을하는 작업 버전이 있습니다.

의심 할 여지없이 Jon과 나는 오늘 나중에 이것을 망치게 될 것입니다.-P

이것 (.proto)의 protobuf-net 버전은 ( 여기):

message Decimal {
  optional uint64 lo = 1; // the first 64 bits of the underlying value
  optional uint32 hi = 2; // the last 32 bis of the underlying value
  optional sint32 signScale = 3; // the number of decimal digits, and the sign
}

다른 팁

Marc와 나는 "일반적인 PB 메시지"라이브러리를 제시 할 계획이있어 .NET 및 Java에서 전환을 이용할 수있는 공통적 인 방식으로 공통적 인 유형 (날짜/시간 및 소수점 스프링이 즉시 사라질 수 있음)을 표현할 수 있습니다. (그리고 다른 사람이 기여하고 싶어하는 모든 것).

.NET을 기꺼이 고수하고 컴팩트 한 것을 찾고 있다면 다음과 같은 것을 가지고 갈 것입니다.

message Decimal {

    // 96-bit mantissa broken into two chunks
    optional uint64 mantissa_msb = 1;
    optional uint32 mantissa_lsb = 2;

    required sint32 exponent_and_sign = 3;
}

부호는 Exponent_and_Sign의 부호로 표시 될 수 있으며 지수는 절대 값입니다.

Mantissa의 두 부분을 선택적으로 만들면 0이 0이 표시됩니다. 매우 소형 (그러나 여전히 0m ~ 0.0000m 등). Exponent_and_Sign은 우리가 정말로 원한다면 선택 사항이 될 수 있습니다.

나는 Marc의 프로젝트에 대해 잘 모르지만 내 포트에서 부분 클래스를 생성하므로 System.decimal과 protobuf.common.decimal (또는 무엇이든) 사이를 부분 클래스로 전환 할 수 있습니다.

나는 원시 소수점 및 DateTime Structs를 가진 protobuf 클래스를 생성하는 후크와 함께 Protobuf-csharp-port의 패치를 모았습니다. 와이어 형식은 현명하게, 두 개의 "내장 된"프로토 메시지로 표시됩니다.

여기 링크가 있습니다:https://code.google.com/p/protobuf-csharp-port/issues/detail?can=2&start=0&num=100&q=&colspec=id%20Type%20Status%20Priority%20Milestone%20owner%20Summarupby=&sort=&sort= 78

Jon이나 Marc의 접근 방식보다 구현하기가 약간 더 간단한 방법은 4로 저장하는 것입니다. sint32 값은 출력에 사소하게 편리하게 매핑됩니다. 십진수.GetBits().

프로토 파일은 다음과 같습니다.

message ProtoDecimal {
    sint32 v1 = 1;
    sint32 v2 = 2;
    sint32 v3 = 3;
    sint32 v4 = 4;
}

변환기는 다음과 같습니다.

public decimal ConvertToDecimal(AbideDecimal value)
{
    return new decimal(new int[] { value.V1, value.V2, value.V3, value.V4 });
}

public ProtoDecimal ConvertFromDecimal(decimal value)
{
    var bits = decimal.GetBits(value);
    return new ProtoDecimal 
    {
        V1 = bits[0],
        V2 = bits[1],
        V3 = bits[2],
        V4 = bits[3]
    }
}

다른 언어에서는 이것이 간단하지 않을 수도 있지만 C#만 대상으로 해야 한다면 다른 접근 방식과 동일한 최대 16바이트를 차지하게 됩니다. (0과 같은 값은 컴팩트하게 저장되지 않을 수도 있습니다. protobuf가 int를 저장하는 방법에 대한 복잡한 세부 사항에 대해 충분히 알고 있지만 나 같은 멍청한 프로그래머에게는 훨씬 더 명확합니다 :)

분명히 당신은해야 할 것입니다 말 경주 성능을 테스트하고 싶지만 그 안에 많은 것이 있는지 의심됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top