[Prev][Next][Index][Thread]

Re: Representing percentage



On Sun, 28 Jan 2001 15:56:28 +0200, Nimi <nimi@better.tv> wrote:
>Hi,
>
> I'm trying to find a simple way to represent percentage. I thought of doing
> it like this:
>
>    define constant <percentage> = limited(<integer>, min: 0, max: 100);
>
> But this is no good if I want to make a generic function that
> specializes on both <integer> (for absolute values, say, the number
> of elements in in a collection passed as another argument) and
> <percentage> (the relative size of the other argument) -
>
> This problem is solved if I do it this way:
>
>    define class <percentage> (<number>)
>        slot p :: limited(<integer>, min: 0, max: 100);
>    end class;
>
> but it doesn't seem very efficient. Is there a better way to do it?

If you have both percentages and absolute sizes floating around your
program, you have to discriminate between the two. The type header in
<percentage> does that for you. You can also add an argument to the
function like

define function foo (c :: <collection>,
                     x :: <integer>,
		     percentage? :: <boolean>)
  if (percentage?)
    // treat x as a percentage
  else
    // treat x as a number of elts
  end if
end function foo;

to discriminate manually. But as you no doubt can see this is really
questionable style.

I have to ask, is your <percentage> class really making your code
inefficient? Unless you have a few million instances of <percentage>
in your program floating around I'd be greatly surprised if it added a
measurable overhead to your program.  Only if it were in an inner
loop, and if that loop had no other allocation, would the
boxing/unboxing overhead of <percentage> be a performance hit. Write
the class, and if (and only if) it causes a bottleneck, optimize it.

[If it is, then here's a Gwydion-specific optimization trick.

define functional class <percentage> (<number>)
  slot p :: limited(<integer>, min: 0, max: 100),
    required-init-keyword: p;
end class <percentage>;

define method functional-== (a :: <percentage>, b :: <percentage>)
 => (ans :: <boolean>)
  a.p == b.p
end method functional-==;

define method functional-== (a :: <percentage>, b :: <object>)
 => (ans :: <boolean>)
  #f
end method functional-==;

define method functional-== (a :: <object>, b :: <percentage>)
 => (ans :: <boolean>)
  #f
end method functional-==;

This creates a class that behaves like <integer> and <character> do --
for these instances identity and equality are the same. The neat bit
is that when the functional object can fit into a word (plus
appropriate type declarations in effect), no memory allocation
happens. Thus it's just as efficient as <integer>.]


Neel



Follow-Ups: References: