From bug-octave-request Wed May 19 13:39:05 1993 Subject: Re: 1:1:5 versus 0.1:0.1:0.5 From: John Eaton To: leisch at neuro dot tuwien dot ac dot at (Friedrich Leisch) Cc: bug-octave Date: Wed, 19 May 93 13:38:59 EDT : I'm using octave, version 0.71.1. : : There is a bug concerning ranges given in the way "x:y:z" : : The following example should be self-explaining: : : octave:1> 1:1:5 : ans = : : 1 2 3 4 5 : : octave:2> 0.1:0.1:0.5 : ans = : : 0.1 0.2 0.3 0.4 This doesn't happen for me on a SPARC or a DECstation. What system are you using? When you specify the limits and increment of a range to be non-integral values, there's no guarantee that the upper limit will be included in the range. I think the best one can do is compute each value in the range as val = base + i * increment i = 0, 1, 2, ... while val is less than or equal to the limit. Since we are dealing with floating point arithmetic, there can be problems. (If you want to guarantee that the endpoints will be in the range, you should use the linspace function.) Unfortunately, version 0.71.1 doesn't use the method above to figure out how many elements there are in a range. Here's a patch that should fix that. If you have any problems with this, or know of a better way, please let me know. *** Range.h~ Wed Feb 10 01:03:21 1993 --- Range.h Wed May 19 10:34:59 1993 *************** *** 90,98 **** inline double Range::min (void) const { return _inc > 0 ? _base : _limit; } inline double Range::max (void) const { return _inc > 0 ? _limit : _base; } - inline int Range::nelem_internal (void) const - { return (int) ((_limit - _base) / _inc + 1); } - #endif /* --- 90,95 ---- *** Range.cc~ Wed Feb 10 01:03:22 1993 --- Range.cc Wed May 19 12:47:58 1993 *************** *** 68,73 **** --- 68,120 ---- return is; } + int + Range::nelem_internal (void) const + { + // Find an approximate number of elements, then do the best we can to + // find the number of elements that we would get if we had done + // something like + // + // nelem = 0; + // while (base + nelem * inc <= limit) + // nelem++; + // + // (for limit > base && inc > 0) + + int ntry = ntry = (int) ((_limit - _base) / _inc); + + if (_limit > _base && _inc > 0) + { + // Our approximation may have been too big. + + while (_base + ntry * _inc > _limit) + ntry--; + + // Now that we are close, get the actual number the hard way. + + while (_base + ntry * _inc <= _limit) + ntry++; + } + else if (_limit < _base && _inc < 0) + { + // Our approximation may have been too big. + + while (_base + ntry * _inc < _limit) + ntry--; + + // Now that we are close, get the actual number the hard way. + + while (_base + ntry * _inc >= _limit) + ntry++; + } + else if (_limit == _base) + ntry = 1; + else + ntry = 0; + + return ntry; + } + /* ;;; Local Variables: *** ;;; mode: C++ *** Thanks, -- John W. Eaton | The exam demonstrates a comminuted, slightly overlapping jwe at che dot utexas dot edu| | angulated fracture of the midfifth metatarsal.