2017-03-10 8 views
1

16 진수 값이 부호없는 정수 및 단일 문자의 원시 메모리 인 16 진수 값을 기반으로 단일 상수를 만들 수있는 방법은 무엇입니까? 나는 같은 것을 할 싶습니다하지만 컴파일되지 않습니다이 시도하고 하나에 16 진수 값을 캐스팅하고 대신 16 진수 값 자체 저장의 캐스트의 결과를 저장합니다 : 내가 얻을델파이의 16 진수 메모리 값을 사용하는 상수 단일

LARGEST_SINGLE_LESS_THAN_ZERO = Single($80800000); 

을 "잘못된 형식 변환"오류입니다. 예를 들어

:

1에 대한 단일 값은 메모리에 $ 3F800000로서 저장된다. 나는 나에게 행운을하지 않고 이와 같은 나는 또한 다른 변화를 시도 1.

대신 $ 3F800000를 사용하여 값을 설정할 수있는 const 만들 수 있도록하고 싶습니다 :

LARGEST_SINGLE_LESS_THAN_ZERO = PSingle(@$80800000)^; 

배경

내가 들어갈 때 사용하는 방법이 다음 작은 하나 하나의 값으로 제공 할 때 :

type 
    PInt32 = ^Int32; 

function NextBefore(const aValue: Single): Single; 
var 
    int32Value: Int32; 
begin 
    // this function ignores special values nan/inf 
    int32Value := PInt32(@aValue)^; 
    if (UInt32(int32Value) = $80000000) or (int32Value = 0) then 
    begin 
    // special handling needed for -0 and 0. We need to go to the smallest 
    // negative number. 
    int32Value := $80800000; 
    end 
    else 
    begin 
    if int32Value >= 0 then 
     Dec(int32Value) 
    else 
     Inc(int32Value); 
    end; 
    Result := PSingle(@int32Value)^; 
end; 

> 또는 < 만 수행 할 수있는 벡터 연산을 사용하므로>> = 및 < =과 동등한 작업을 수행 할 수 있으므로이 방법이 유용합니다. 우리는 종종 0에 대해 확인 그래서 우리는 데이터> = 0을 모두 얻을 필요로하는 곳에 우리는 같은 것을 할 :

MyVector.ThresholdGT(NextBefore(0)); 

이러한 유형의 작업에 대한 일정과 다른 개발자를 제공하기 위해 더 좋은 것이다. 번호가 변수가 아니기 때문에 아래 PSingle 형식을 사용하려고하면 작동하지 않습니다.

+0

'Int32'의 범위를 초과하는'Single' 값을 전달하면 코드가 정의되지 않은 동작을한다고 생각합니다. 'Single' 비트를'Int32' 비트로 재 해석하는 이유는 무엇입니까? 부동 소수점 연산이 아닌 정수 수학을 수행하고 있습니다. 그게 네가 정말로 원하는거야? 가장 큰 양수 및 음수 '단일'값은 가장 큰 양수 및 음수 'Int32'값보다 훨씬 큽니다. 'System.Math' 단위는'MinSingle'과'MaxSingle' 상수를가집니다. –

+0

@remy 그것이 작동하지 않는 이유입니다. 나는 그 질문을 수정할 것이다. 메모리에 표현되는대로 단일 값이 필요합니다. – Graymatter

+0

하지만 왜? 당신은 정말로 무엇을 해결하려고합니까? 예제를 제공 할 수 있습니까? 왜 더 이상 뭔가를하지 않습니까? '(aValue = -0.0) 또는 (aValue = 0.0)이면 Result : = -WhateverValueYouWant else if (aValue> 0.0) then Result : = aValue - 1.0 그 밖의 값 : = aValue + 1.0 끝, ' –

답변

2

언어의 제약 조건을 지키는 것이 어렵지 않습니다. 아마도 여러분이 할 수있는 최선의 방법은 정수 필드와 단일 필드가 겹쳐진 변형 레코드 유형을 만드는 것입니다.

type 
    TSingleIntegerVariantRec = record 
    case Integer of 
     0: (I: Integer); 
     1: (S: Single); 
    end; 

일단 해당 유형을 사용할 수있게되면 정수 필드를 사용하여 유형화 된 상수를 선언 할 수 있지만 단일 입력란을 읽습니다.

const 
    LARGEST_SINGLE_LESS_THAN_ZERO: TSingleIntegerVariantRec = (I: $80800000); 
.... 
MyVector.ThresholdGT(LARGEST_SINGLE_LESS_THAN_ZERO.S); 

당신이 .S를 생략 할 수있는 것입니다 당신이 Single에 암시 적 캐스트 연산자를 구현할 수있는 여분의 뉘앙스를 추가합니다. 그 연산자를 인라인으로 만들었다면 방출 된 코드가 매우 효율적이라고 생각합니다.

이것은 사용자가 묻는 바를 나타내지 만 매우 우아하다고 주장하지는 않습니다. 우리는 다음 값을 라이브러리 함수로 사용하도록 코드를 옮겨서 0을 전달하고 라이브러리의 소비자를 이러한 구현 세부 사항으로부터 보호 할 수 있습니다.그런 다음이 코드의 소비자가 단순히 쓰기

procedure TMyVector.ThresholdGTequal(const Value: Single); 
begin 
    ThresholdGT(NextBefore(Value)); 
end; 

:

MyVector.ThresholdGTequal(0); 

을하고 밥맛의 모든 잊기 남아

즉 당신은 다음과 같이 구현 된 ThresholdGTequal 방법을 추가 구현 세부 사항. 이 코드에 의해 변경 될 수없는 방식에서의 16 진수 값을 가진 하나의 정수를 선언하기 위해

+0

불행하게도 [Intel IPP] (https://software.intel.com/en-us/node/504068)에는 Threshold_GT 연산 만 있고 Threshold_GTEqual 연산은 없습니다. 솔루션의 또 다른 개선점은 클래스 연산자 Implicit (a : TSingleIntegerVariantRec) : Single; 연산자 오버로드를 추가하여 '.S'에 대한 필요성을 제거하는 것입니다. – Graymatter

+1

@Graymatter 그래서 Threshold_GT (NextBefore (Value))를 호출하여 Threshold_GTEqual (Value)를 구현합니다. 그것은 발신자를이 모든 것으로부터 보호합니다. 그것은 분명히 당신이해야 할 일입니다. 나는 당신이 인생을 너무나 힘든 일을 시도함으로써 너무 힘들게 만들고 있다고 생각합니다. –

+0

무슨 뜻인지 알 겠어. 이것은 확실히 내가 사용할 솔루션입니다. – Graymatter

2

, 그것은 두 단계로 수행 될 수

const 
    iLARGEST_SINGLE_LESS_THAN_ZERO : Int32 = $80800000; 
var 
    LARGEST_SINGLE_LESS_THAN_ZERO : Single absolute iLARGEST_SINGLE_LESS_THAN_ZERO; 

LARGEST_SINGLE_LESS_THAN_ZERO의 값을 변경하려고 것 컴파일러 오류 : Left side cannot be assigned to을 제공하십시오.

+0

또한 [신호 NaN을 사용하기 쉬운 방법으로 만들 수 있습니까?] (http://stackoverflow.com/a/16252964/576719)를 참조하십시오. –