意想不到的 Ada 类型兼容性

问题描述 投票:0回答:2

为什么伏特、安培和欧姆兼容?


with ada.text_io; use ada.text_io;
                                                                    
procedure main is                                                   
    type Volts is delta 1.0 / 2.0 ** 12 range -45_000.0 .. 45_000.0;
    type Amps is delta 1.0 / 2.0 ** 16 range -1_000.0 .. 1_000.0;   
    type Ohms is delta 0.125 range 0.0 .. 1.0E8;                    
                                                                    
    V : Volts := 1.0;                                               
    A : Amps := 1.0;                                                
    R1 : Ohms := 1.0;                                               
    R2 : Ohms := 1.0;                                               
                                                                   
begin                                             
                     
    v := A * (R1 + R2);
                       
    put_line(V'Img);   
                       
end main;  

如果类型定义为

new Float
,我在编译过程中会收到以下异常:


main.adb:22:12: error: invalid operand types for operator "*"
main.adb:22:12: error: left operand has type "Amps" defined at line 5
main.adb:22:12: error: right operand has type "Ohms" defined at line 6

我期望使用带有 Volts 的类型来定义与其他类型不兼容的新类型,因为它不是定点类型的显式子类型。

ada gnat
2个回答
2
投票

自 Ada 95 起,Ada 标准明确允许(预定义)不同定点类型操作数的乘法和除法 - 请参阅 http://www.ada-auth.org/standards/22rm/html/RM-4 -5-5.html,第 18 段——但仅在结果也预计为某种定点类型的情况下(参见第 19.1/2 段)。不同定点类型之间的加法和减法不是预定义的,当然不同定点类型在例如中是不兼容的。参数或赋值。

至于为什么不同类型之间允许使用*和/,我没有明确的答案。相关的 Ada 问题之一 (http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ais/ai-00364.txt?rev=1.15) 有 Randy Brukardt 的简短评论:“ ...Ada 95 规则的出现是因为人们抱怨必须在以下位置编写类型转换: A := B * 5.0; 感觉这让艾达看起来很糟糕。”。

同一个人工智能也有批评新规则的评论......所以意见不同。


0
投票

定点值的规范表示是整数;表示的值是存储的整数乘以该类型的small(对于十进制定点类型,smalldelta相同;对于普通定点类型,它们可能不同)。

所以对于像这样的类型

type FP is delta 0.001 digits 10;

值 12.345 和 67.890 将分别存储为 12_345 和 67_890。当您将它们相乘时,您会得到 838_102_050,它代表 838.102_050,其中 small 为 0.000_001。因此,相同类型的值相乘会产生不同类型的值。当操作数属于不同类型时,类似的情况也适用。因此,该语言根据 universal_fixed 定义乘法和除法,尽管结果必须显式或隐式(如您的示例中所示)转换为命名类型,正如 Holsti 指出的那样。

分裂也会出现类似的问题; 67_890 / 12_345 产生 5,small 为 1.0。

这样做的另一个结果是,您可以将定点值乘以或除以整数,并得到相同定点类型的值,无需任何调整:3 * 12_345 = 37_035,表示 37.035 = 3 * 12.345。类型

Integer
的乘法和除法运算符由语言定义。

© www.soinside.com 2019 - 2024. All rights reserved.