-1

I have the following code:

function Extenso(nb: real); string;
var
  total: real;
begin
  total := Trunc(nb);
  ...
  Result := ...;
end;

This function returns a string describing the number in full, for a country that has no cents, therefore the Trunc.

When input param nb comes in as 790209.00 (my error case, with decimals 0), strangely enough the result of Trunc is 790208 on debugger. Can someone please try to explain that ?!? I'm on Delphi XE3 update 2, with IDE fix pack 5.93, Windows 10 Pro 64.

Edit: as a clarification to the question, there's a business rule involved here, customer will accept rounds up to the result, but not down. Thanks @Dsm and @CraigYoung to your contributions.

vortal
  • 139
  • 2
  • 9
  • How is the value `790209.00` set? Does `s := Extenso(790209.0);` give the above result? If not then, it could be that the value is `790208.9995` or so, but rounded up when presented with two decimals. – LU RD Mar 29 '17 at 14:36
  • Looks like pretty much the same as http://stackoverflow.com/questions/1398295/trunc-function – Free Consulting Mar 29 '17 at 14:51
  • What you are describing cannot be reproduced. Show a [mcve]. – David Heffernan Mar 29 '17 at 14:51
  • The input param **nb** is a result of a calculation, in this case, 33.30 * 23730.00, also stored in a real and passed into function. But @Dsm made it perfectly clear. Will use round(nb + 0.5) instead. – vortal Mar 29 '17 at 15:07
  • 1
    `33.3 * 23730.0 = 79020.9` which is definitely not an integer. All you had to do was the most basic debugging. Why are today's programmers so deficient in debugging skills? In many ways I think this site is a cause. Novice developers ask here when they get stuck instead of being forced to learn to debug and think for themselves. – David Heffernan Mar 30 '17 at 07:53
  • 1
    @DavidHeffernan I understand your frustration, but please [be-nice] if you leave comment on OP's post and keep meta discussions to meta. – Petter Friberg Mar 30 '17 at 07:57
  • 1
    @PetterFriberg That is being nice. The asker will be so much better off by learning to debug. – David Heffernan Mar 30 '17 at 08:11
  • I appreciate all the constructive comments, but won't discuss off topics. @DavidHeffernan redo your calculations on your comments above, and please, do not judge professionals by a badge on Stack Overflow. – vortal Mar 31 '17 at 12:16
  • 1
    Retaining pride has got to be more important than learning to debug, I get it – David Heffernan Mar 31 '17 at 12:19
  • 1
    Possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Disillusioned Mar 31 '17 at 15:34
  • @vortal Using `Round(nb + 0.5)` doesn't solve your problem. E.g. if `nb = 1.25`, you'l return `2`! You quite clearly do **not understand** the issues involved yet. Please read the duplicate I linked and related documentation thoroughly. – Disillusioned Mar 31 '17 at 15:41

1 Answers1

3

You need to use round rather than trunc here. With type real, the value is not quite exact, so 790209.00 might really be 790208.999999999 for example, and truncing this will give the value shown. Of course, if you might have a value ending in .5, rounding might not give you what you want every time, and you might need to consider some function like

Trunc( nb + 0.000001);
Dsm
  • 5,870
  • 20
  • 24
  • The value 790209 is well within the precision range of `Real`. It is represented as it's exact integer value. – Rob Kennedy Mar 29 '17 at 16:06
  • @RobKennedy: Unless the value 790209 is a calculated value (which it is - see comment above - 33.3 * 23730), in which case the value may very well be 790208.99, as 33.3 is not precisely presentable in an IEEE floating point type. – HeartWare Mar 29 '17 at 17:44
  • This is genuinely terrible advice. A value of `1.99999993562` that is intended to truncate to `1` would instead return `2`. The correct advice would be to guide OP to understanding the concepts of how floating point math works. Understand the alternatives and the pros and cons of various approaches. Advising a lazy hack-around simply yields a fundamentally flawed solution. – Disillusioned Mar 31 '17 at 15:49
  • @CraigYoung It depends what you are trying to achieve that value was arrived at, and that was not clear from the question. The fundamental advice was to use round, but it was clear that the value was not a genuine integer and must be calculated in some way. But how? and what kind of results does it achieve? And is 1.99999999352 is likely to need to be rounded down? – Dsm Apr 03 '17 at 07:27
  • @Dsm Going by the fact that OP was using `Trunc`: ***yes*** it's reasonable to expect that `1.99999999352` should be ***truncated*** down. And ***no***, it doesn't "depend on what you're trying to achieve". Adding an _arbitrary constant_ to hack around a lack of understanding of floating point numbers because the "right result looks wrong" is as silly as: adding `1` to the preliminary result of all other arbitrary arithmetic because you don't like numbers that end in `0`. – Disillusioned Apr 03 '17 at 10:21
  • @CraigYoung Although I understand and agree in principle what you are saying (which is why I recommended **Round**) I disagree with the specifics, because the question was complaining that 790209.00 was being truncated to 790208. Now 790209.00 could well have been 790208.999999352 (to misquote your example). I am not recommending adding an arbitrary constant, simply commenting that depending on circumstances that may be necessary because I don't know whether he has numbers like 1.0510, but if he does, round may not work for him. – Dsm Apr 03 '17 at 11:04