Issue 1899: Rounding and truncation of Fixed (cxx_revision) Source: (, ) Nature: Uncategorized Issue Severity: Summary: Summary: What happens if I do: Fixed f = "999999.999"; Fixed f2; f2 = f.round(3, 1); // ??? f2 = f.truncate(3, 1); // ??? Should these throw DATA_CONVERSION? I think so -- if we agree on this, the spec should state it. Resolution: Revised Text: Actions taken: August 31, 1998: received issue Discussion: End of Annotations:===== Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Mon, 31 Aug 1998 13:31:16 +1000 (EST) From: Michi Henning To: issues@omg.org, cxx_revision@omg.org Subject: Rounding and truncation of Fixed What happens if I do: Fixed f = "999999.999"; Fixed f2; f2 = f.round(3, 1); // ??? f2 = f.truncate(3, 1); // ??? Should these throw DATA_CONVERSION? I think so -- if we agree on this, the spec should state it. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Mon, 31 Aug 1998 13:59:04 +1000 (EST) From: Michi Henning To: cxx_revision@omg.org Subject: Re: Rounding and truncation of Fixed On Mon, 31 Aug 1998, Michi Henning wrote: > What happens if I do: > > Fixed f = "999999.999"; > Fixed f2; > > f2 = f.round(3, 1); // ??? > f2 = f.truncate(3, 1); // ??? > > Should these throw DATA_CONVERSION? I think so -- if we agree on > this, > the spec should state it. Thinking some more about this, it appears that round() and truncate() require only one parameter: class Fixed { // ... Fixed round(UShort scale) const; Fixed truncate(UShort scale) const; // ... }; That is because as far as I can see, truncation and rounding always only apply to *fractional* digits, so there is no point in requiring the total number of digits as a parameter. Taking that path would eliminate the issue of what should happen in the above cases altogether, because a meaningless conversion would be impossible. Of course, the question is whether I should be able to round and truncate the integral digits as well. If so, we could use class Fixed { // ... Fixed round(Short scale) const; Fixed truncate(Short scale) const; // ... }; Note the change of parameter from UShort to Short. In that case, we could use negative scale values to round the integral part: Fixed f = "999.05"; cout << f.truncate(1) << endl; // 999.0 cout << f.round(1) << endl; // 999.1 cout << f.truncate(0) << endl; // 999 cout << f.round(0) << endl; // 999 cout << f.truncate(-1) << endl; // 990 cout << f.truncate(-2) << endl; // 900 cout << f.truncate(-3) << endl; // 0 cout << f.truncate(-4) << endl; // 0 cout << f.round(-1) << endl; // 1000 cout << f.round(-2) << endl; // 1000 cout << f.round(-3) << endl; // 1000 cout << f.round(-4) << endl; // 0 I'm not sure whether that's necessary, but it seems that either way, round() and truncate() require only a single parameter? Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: Sender: jon@floorboard.com Date: Sun, 30 Aug 1998 21:49:43 -0700 From: Jonathan Biggar To: Michi Henning CC: cxx_revision@omg.org Subject: Re: Rounding and truncation of Fixed References: Michi Henning wrote: > Thinking some more about this, it appears that round() and > truncate() > require only one parameter: > > class Fixed { > // ... > Fixed round(UShort scale) const; > Fixed truncate(UShort scale) const; > // ... > }; > > That is because as far as I can see, truncation and rounding always > only > apply to *fractional* digits, so there is no point in requiring the > total number of digits as a parameter. Taking that path would > eliminate > the issue of what should happen in the above cases altogether, > because > a meaningless conversion would be impossible. I suppose. > Of course, the question is whether I should be able to round and truncate > the integral digits as well. If so, we could use > > class Fixed { > // ... > Fixed round(Short scale) const; > Fixed truncate(Short scale) const; > // ... > }; > > Note the change of parameter from UShort to Short. In that case, we could > use negative scale values to round the integral part: > > Fixed f = "999.05"; > > cout << f.truncate(1) << endl; // 999.0 > cout << f.round(1) << endl; // 999.1 > cout << f.truncate(0) << endl; // 999 > cout << f.round(0) << endl; // 999 > cout << f.truncate(-1) << endl; // 990 > cout << f.truncate(-2) << endl; // 900 > cout << f.truncate(-3) << endl; // 0 > cout << f.truncate(-4) << endl; // 0 > cout << f.round(-1) << endl; // 1000 > cout << f.round(-2) << endl; // 1000 > cout << f.round(-3) << endl; // 1000 > cout << f.round(-4) << endl; // 0 We explicitly got rid of negative scale for CORBA 2.3 because it was non-portable, so we don't want to reintroduce it here. If someone really wants to do f.round(-1) then just do (f/10.0).round(0)*10.0 -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Mon, 31 Aug 1998 15:21:39 +1000 (EST) From: Michi Henning To: Jonathan Biggar cc: cxx_revision@omg.org Subject: Re: Rounding and truncation of Fixed On Sun, 30 Aug 1998, Jonathan Biggar wrote: > Michi Henning wrote: > > > > That is because as far as I can see, truncation and rounding > always only > > apply to *fractional* digits, so there is no point in requiring > the > > total number of digits as a parameter. Taking that path would > eliminate > > the issue of what should happen in the above cases altogether, > because > > a meaningless conversion would be impossible. > > I suppose. There is also another hairy issue that sort of crept in through the back-door. As they stand, round() and truncate() actually *set* both digits and scale: The round and truncate functions convert a fixed value to a new value with the specified digits and scale. However, that creates an inconsistency, because for fixed_digits() and fixed_scale(), the text says: The fixed_digits() and fixed_scale() functions return the smallest digits and scale value that can hold the complete fixed-point value. The inconsistency arises because: Fixed f1 = "0D"; // Implicitly fixed<1,0> Fixed f2 = f1.round(3, 2); // Returns 0.00 cout << f2.fixed_digits() << endl; // Prints 1, not 3 cout << f2.fixed_scale() << endl; // Prints 0, not 2 Another inconsistency: If round and truncate *really* behave as specified (that is, *set* the digits and scale), the CORBA::Any::from_fixed() and CORBA::Any::to_fixed() helpers really are redundant, because I could achieve the same thing with round(), truncate(), and Any::operator<<=() and Any::operator>>=() for Fixed. I think that dropping the digits parameter from both round() and truncate() would be best because it is consistent -- I *cannot* control the internal representation (digits and scale) of a Fixed value at all. Instead, I just use it like a floating-point value until I'm ready to pass it to an operation. If I want to make that safe, I need to call fixed_digits() before passing the value across an interface to make sure the value fits with the signature of the operation. > > Of course, the question is whether I should be able to round and truncate > > the integral digits as well. > We explicitly got rid of negative scale for CORBA 2.3 because it was > non-portable, so we don't want to reintroduce it here. If someone > really wants to do f.round(-1) then just do (f/10.0).round(0)*10.0 Yes, I was worried about that too. I agree that negative scale values are bad, given that the IDL declaration syntax can't handle them either. If we just leave the scale parameters for round() and truncate() as UShort, and the question doesn't arise. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html