From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,cb3f9900b9cf2da6 X-Google-Attributes: gid103376,public From: eachus@spectre.mitre.org (Robert I. Eachus) Subject: Re: Truncation of FLOAT values Date: 1996/04/22 Message-ID: #1/1 X-Deja-AN: 150846801 references: <4l6bjn$b96@cliffy.lfwc.lockheed.com> <4l8a6h$274@newsbf02.news.aol.com> organization: The Mitre Corp., Bedford, MA. newsgroups: comp.lang.ada Date: 1996-04-22T00:00:00+00:00 List-Id: In article dewar@cs.nyu.edu (Robert Dewar) writes: > John Herro said > "function Floor(X : in Float) return Integer is > Answer : Integer := Integer(X); > begin > if Float(Answer) > X then > Answer := Answer - 1; > end if; > return Answer; > end Floor;" > Although this will typically work, Ada semantics do not guarantee that > it will work. While Professer Dewar is quite correct, a more helpful answer is: function Floor(X : in Float) return Integer is Answer : Integer; begin Answer := Integer(X); if Float(Answer) - X > 0.0 then return Answer - 1; end if; return Answer; exception when Constraint_Error => if X - Float(Integer'LAST - 1) > 0.0 then if X - Float(Integer'LAST) < 0.0 then return Integer'LAST - 1; elsif X - Float(Integer'LAST) < 1.0 then return Integer'LAST; else raise; end if; elsif Float(Integer'FIRST + 1) - X < 0.0 then if Float(Integer'FIRST) - X >= 0.0 then return Integer'FIRST; else raise; end if; end Floor; Almost all floating point compares are against zero, the exception is the case where you are testing for X < Integer'LAST + 1 in the three special cases dealt with in the exception handler. Yes, there are still cases where the result returned by this function will not be "mathematically correct" but they will only occur when X is converted to a model number whose fractional part is zero as a side effect of the call. In other words on most hardware, Floor(1_000_000_000.0 - Float'Epsilon) will return 1_000_000_000. (On most other implementations, it will raise an exception.) This is a known problem with any implementation of floating point arithmetic, and has to be dealt with in the design of floating point algorithms. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is...