我可以将值钳制到Ada中的某个范围内吗?

我可以将值钳制到Ada中的某个范围内吗?,ada,Ada,在Ada中是否有一种很好的方法将值钳制(剪裁?、强制?)到某个范围? 我现在已经这样做了: timer := Integer'Max(timer, Integer(Half_Word'First)); timer := Integer'Min(timer, Integer(Half_Word'Last)); TIM8.TIM.ARR := Half_Word(timer); 但这有点笨重,我想将变量计时器钳制在半个字的范围内。Ada没有内置的方法来实现这一点。如果这是您将在不同类型上重复执行的

在Ada中是否有一种很好的方法将值钳制(剪裁?、强制?)到某个范围? 我现在已经这样做了:

timer := Integer'Max(timer, Integer(Half_Word'First));
timer := Integer'Min(timer, Integer(Half_Word'Last));
TIM8.TIM.ARR := Half_Word(timer);

但这有点笨重,我想将变量计时器钳制在半个字的范围内。

Ada没有内置的方法来实现这一点。如果这是您将在不同类型上重复执行的操作,那么像这样的泛型可能会有所帮助:

generic
     type Source_Type is range <>;
     type Destination_Type is range <>;
function Saturate (X : Source_Type) return Destination_Type;

function Saturate (X : Source_Type) return Destination_Type is
    Result : Source_Type;
begin
    Result := Source_Type'Max (X, Source_Type (Destination_Type'First));
    Result := Source_Type'Min (Result, Source_Type (Destination_Type'Last));
    return Destination_Type (Result);
end Saturate; 

...

function Saturate_To_Half_Word is new Saturate (Integer, Half_Word); 

... 

TIM8.TIM.ARR := Saturate_To_Half_Word(timer);
您必须仔细编写代码,以避免类型冲突,同时避免引发
Constraint\u错误

编辑2:我有
第一个
最后一个
向后。固定的

编辑3:按照Simon的建议,这也会起作用:

function Saturate (X : Source_Type) return Destination_Type is
    type Largest_Int is range System.Min_Int .. System.Max_Int;
    Result : Largest_Int;
begin
    Result := Largest_Int (X);
    Result := Largest_Int'Max (Result, Largest_Int (Destination_Type'First));
    Result := Largest_Int'Min (Result, Largest_Int (Destination_Type'Last));
    return Destination_Type (Result);
end Saturate; 

这看起来更简单,但效率可能稍低,因为它在运行时涉及更多类型转换。(请注意,前面示例中的复杂外观条件都是可在编译时计算的条件,因此不应生成任何代码——此外,它可能会导致消除
'Max
和/或
'Min
操作。这是假设编译器使用“宏扩展”泛型实例化的模型,就像GNAT一样。一个真正优秀的编译器可能也能够在后一段代码中找出相同类型的优化,但这更难。)

Ada没有一种内置的方法来实现这一点。如果这是您将在不同类型上重复执行的操作,那么像这样的泛型可能会有所帮助:

generic
     type Source_Type is range <>;
     type Destination_Type is range <>;
function Saturate (X : Source_Type) return Destination_Type;

function Saturate (X : Source_Type) return Destination_Type is
    Result : Source_Type;
begin
    Result := Source_Type'Max (X, Source_Type (Destination_Type'First));
    Result := Source_Type'Min (Result, Source_Type (Destination_Type'Last));
    return Destination_Type (Result);
end Saturate; 

...

function Saturate_To_Half_Word is new Saturate (Integer, Half_Word); 

... 

TIM8.TIM.ARR := Saturate_To_Half_Word(timer);
您必须仔细编写代码,以避免类型冲突,同时避免引发
Constraint\u错误

编辑2:我有
第一个
最后一个
向后。固定的

编辑3:按照Simon的建议,这也会起作用:

function Saturate (X : Source_Type) return Destination_Type is
    type Largest_Int is range System.Min_Int .. System.Max_Int;
    Result : Largest_Int;
begin
    Result := Largest_Int (X);
    Result := Largest_Int'Max (Result, Largest_Int (Destination_Type'First));
    Result := Largest_Int'Min (Result, Largest_Int (Destination_Type'Last));
    return Destination_Type (Result);
end Saturate; 

这看起来更简单,但效率可能稍低,因为它在运行时涉及更多类型转换。(请注意,前面示例中的复杂外观条件都是可在编译时计算的条件,因此不应生成任何代码——此外,它可能会导致消除
'Max
和/或
'Min
操作。这是假设编译器使用“宏扩展”通用实例化的模型,就像GNAT一样。一个真正优秀的编译器可能也能够在后一段代码中找出相同类型的优化,但这更难。)

您可以使用默认值使其更易于使用——最大的问题[维护方面]是,看起来进行的事情比实际情况要多,最大的缺点是,编译器在编译时没有检查/强制执行
目标类型
作为
源类型
子集的约束

通用
类型源\类型为范围;
类型目的地\类型为范围;
S_First:Long_Long_Integer:=Long_Long_Integer(源类型'First);--'修理
S_Last:Long_Long_Integer:=Long_Long_Integer(源类型'Last);--'婴儿车
D_First:Long_Long_Integer:=Long_Long_Integer(目的地类型'First);--'语法
D_Last:Long_Long_Integer:=Long_Long_Integer(目的地类型'Last);--'突出
函数饱和(X:源类型)返回目标类型
使用Pre=>
D_优先>=S_优先
最后一刻,
目的地类型=>J
);

您可以使用默认设置使其更易于使用--最大的问题[维护方面]是,它看起来比实际情况更复杂,最大的缺点是,编译器在编译时没有检查/强制执行
目标类型
作为
源类型
子集的约束

通用
类型源\类型为范围;
类型目的地\类型为范围;
S_First:Long_Long_Integer:=Long_Long_Integer(源类型'First);--'修理
S_Last:Long_Long_Integer:=Long_Long_Integer(源类型'Last);--'婴儿车
D_First:Long_Long_Integer:=Long_Long_Integer(目的地类型'First);--'语法
D_Last:Long_Long_Integer:=Long_Long_Integer(目的地类型'Last);--'突出
函数饱和(X:源类型)返回目标类型
使用Pre=>
D_优先>=S_优先
最后一刻,
目的地类型=>J
);

你能不能声明一下
定时器:半个字?——那样的话,你必须首先计算正确。计时器是什么类型的?(为什么不能使用半个字作为计时器类型?)。计时器来自于涉及大量数字的计算(时钟频率、时钟分频器等),所以我不能用半个字来计算。总之:我不明白为什么人们认为提问者不知道他真正想要什么。我们不能先假设提问者比我们其他人更了解他要完成的任务吗?我可以理解,新手经常会提出低劣的解决方案,需要得到一些新的想法。但作为一个非新手,当我问了一个问题,其他人认为他们知道我的目的是什么,并告诉我“你为什么不改做WXYZ”,我觉得这很侮辱人。在这一点上,我倾向于同意AJB。我有一个编码器来驱动马达的速度。毫无疑问,在最快的速度之后的下一个速度是停止的。但是,当你试图获得高于最高速度的速度时,你只需要获得最高速度,这是完全可以接受的。我在最后一个阶段这样做,这样即使我用软件发送速度并且出错,它也会被夹紧而不会被包装?——那样的话,你必须首先计算正确。计时器是什么类型的?(为什么不能使用半个字作为计时器类型?)