how to write real fractions.

16 views
Skip to first unread message

JaCo Stuifbergen

unread,
Oct 24, 2020, 3:56:16 PM10/24/20
to juggling-interchange-format
I want to react to Florian's remark, in the thread "from causal diagram to physical throw"

Maybe we should also allow real fractions?

In social site-swaps, fractions are often rendered decimally, with sometimes round-off errors:

1/5 = 0.2
1/4 = 0.25
1/3 = 0.3
2/5 = 0.4
1/2 = 0.5
3/5 = 0.6
2/3 = 0.7
3/4 = 0.75
4/5 = 0.8

I think that I have never seen a higher denominator (1/6, 1/7, 1/8) in a pattern.
(and I think that jugglers who can actually juggle such a small delay are even rarer)

But JIF should prepare for future developments (and simulators can handel small fractions), and poly-rhythms might lead to higher denominators (imagine juggler A in a 3/4 polyrythm, and B in 3/5, where A's 4 cycle has the same frequency as B's "3" cycle. This would lead to a ratio 5/9)  

There is a useful mathematical property:
If n < 10^k,
we need only k decimals to distinguish all fractions p/n (with p = 1, 2, ..., n)
example:
8 is less than 10 = 10^1 , so we need only 1 decimal:
1/8 = 0.1
2/8 = 0.3
3/8 = 0.4
4/8 = 0.5
5/8 = 0.6
7/8 = 0.9
8/8 = 1.0

If we want to distinguish fractions of, say, 8 and 9, we must use 72 as the denominator (8*9 =72).
So 2 decimals will be enough.
For 6 and 8, the denominator would be 24 (the smallest common multiple of 6 and 8). Still 2 decimals.
There are simple algorithms to find the smallest common multiple, so it is easy to know how many digits we need to distinguish the fractions that we need.

The denominator that the pattern uses, could be specified in the meta-data, so we can convert back to exact fractions.

Otherwise, I can think of an algorithm that decides that 0.33 means 1/3 and 0.34 means something different (I think 17/50):
- take n = 2
- multiply by n (2 * 0.33 = 0.66)
- round of (0.66 --> 1)
- divide by n (1/2 = 0.5)
- is this the original number? then n is the denominator
  otherwise, increase n by 1 and repeat.
This algorithm would find 3*0.33=0.99 --> 1.0 --> 1/3 = 0.33 (OK!)
and 3*0.34=1.02 --> 1.0 --> 1/3 = 0.33 (not equal to 0.34, so continue)

Such an algorithm will find the exact multiples of 1/8 and 1/9, if 2 digits are present.

For physical parameters (for example, a dwell duration) we do not require perfect fractions, only the specified precision.
So the software may treat 0.33 as it wants: 33/100, or 1/3 , because 1/3 is rounded off to 0.33
But 0.34 should never be treated like 1/3, because 1/3 would be rounded off to 0.33, not to 0.34
0.3 however, would be converted to 1/3, so if you want a value to be 0.3 , you should write 0.30

So, my proposal is:
- use decimal fractions everywhere
- specify (in the metadata) to which fraction decimal fractions should be converted
  or derive this by an algorithm
- if a decimal fraction cannot be converted correctly, it will remain a decimal fraction.
  So physical parameters won't suffer from inaccuracy - as long as you write out all decimals. (I admit that this can lead to errors)

By the way, if all fractions of 2, 3, etc. till 10, can be expressed as multiples of 1/2520.
So we would need 4 digits for 1/2, 1/3, 1/4, till 1/10.

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================

Florian Pesth

unread,
Oct 24, 2020, 6:30:20 PM10/24/20
to juggling-interchange-format
Yes, thanks, this suggestion would work as well if want to avoid a
fraction type. What might be harder to do might be to seperate the
different "beat groups".

I think of two jugglers having let's say a speed difference of 2/3 but
both throwing siteswaps in their local "beat group" and passing some
props.

Would the software be able to determine the most simple beat
difference and siteswap of each juggler?

I guess there could be a canonical most simple form but it could make
implementation a bit more difficult.

Not saying I'm opposing the suggestion, but this is something one
should maybe consider.


Am Sat, 24 Oct 2020 21:56:03 +0200
schrieb JaCo Stuifbergen <j.c.stu...@gmail.com>:

Adrian Goldwaser

unread,
Oct 25, 2020, 12:10:47 AM10/25/20
to juggling-interchange-format
> Otherwise we get computationaly nasty numbers like 1.3333333.
I personally don't think this matters, we would be comparing numbers with an epsilon (e.g. 1e-8) margin so it doesn't matter if things are a bit off - it won't be visible in causals/animators and all the programs would automatically correct for it if needed as a consequence of doing valid floating point arithmetic. It will be far less readable in the raw JIF but I don't think we're optimising for that.

That said I find this discussion really interesting because I wanted to do something similar for the passing siteswap library I've been writing for my causal editor, what I settled on was:
If something was < 1e-2 distance from a fraction with denominator < 10 then set it to that fraction.
If there is a number of jugglers divisible by 3 then treat 0.3 and 0.6 as 1/3 and 2/3 (we can't always convert these as 5 person patterns need 0.6 to be 0.6), I'd never seen 0.7 used instead of 0.6 for 2/3rds before (or had forgotten if I had) - will make sure I support that too, though again if you have 10 jugglers you want 0.7 to be 0.7.
This works for anything up to 10 jugglers which is enough for the purposes of passing siteswap (writing out a 22-handed siteswap in passing notation is a bit far anyway IMO), and often works for more too. However the reason I did all of this was to simplify reading/writing the siteswaps, I'm not convinced that the same argument applies to JIF as it will be written/read by programs.

--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/juggling-interchange-format/20201025003017.5bc01303%40babbage.

JaCo Stuifbergen

unread,
Oct 25, 2020, 7:45:36 AM10/25/20
to juggling-interchange-format
An animator won't show the difference between 1.33333 and 4/3 but in some cases, we may wish to know whether a patterns is a social siteswap with shift 1/3, or whether a number like 1.33 is a coincidence.
Some pattern editor may want to recognise such symmetries.

1e-2 seems indeed precise enough to distinguish all fractions with numerators up to 10.
But I prefer to set a standard that can be extended to smaller fractions.

of course, a notation like {numerator: 3 , denominator: 5} would be all right for me.

JaCo Stuifbergen

unread,
Oct 26, 2020, 7:03:37 AM10/26/20
to juggling-interchange-format
On second thoughts,
I think that an easier way to distinguish fractions will be by explicit mention of the denominator.

so 2 2/3 will not be written as 2.6667 but as {numerator:8, denominator:3} because 8/3 = 2 2/3

We can still use decimal fractions by setting the denominator to 1, like
{ holdTime:{numerator: 1.55, denominator:1}, .........}

It  will then be necessary to specify which numbers need a denominator.
Or we may specify that all numbers will be given as a fraction.
(even the number of jugglers...)


Christian Helbling

unread,
Oct 26, 2020, 7:57:10 AM10/26/20
to juggling-inte...@googlegroups.com
On 2020-10-25 05:10, Adrian Goldwaser wrote:
> > Otherwise we get computationaly nasty numbers like 1.3333333.
> I personally don't think this matters, we would be comparing numbers with an epsilon (e.g. 1e-8) margin so it doesn't matter if things are a bit off - it won't be visible in causals/animators and all the programs would automatically correct for it if needed as a consequence of doing valid floating point arithmetic. It will be far less readable in the raw JIF but I don't think we're optimising for that.

> That said I find this discussion really interesting because I wanted to do something similar for the passing siteswap library I've been writing for my causal editor, what I settled on was:
> If something was < 1e-2 distance from a fraction with denominator < 10 then set it to that fraction.
> If there is a number of jugglers divisible by 3 then treat 0.3 and 0.6 as 1/3 and 2/3 (we can't always convert these as 5 person patterns need 0.6 to be 0.6), I'd never seen 0.7 used instead of 0.6 for 2/3rds before (or had forgotten if I had) - will make sure I support that too, though again if you have 10 jugglers you want 0.7 to be 0.7.
> This works for anything up to 10 jugglers which is enough for the purposes of passing siteswap (writing out a 22-handed siteswap in passing notation is a bit far anyway IMO), and often works for more too. However the reason I did all of this was to simplify reading/writing the siteswaps, I'm not convinced that the same argument applies to JIF as it will be written/read by programs.

I agree with Adrian here and just go with floating point numbers for simplicity.
I think all the use cases on lukas' list are doable fine with them.

I see the following two use-cases where it could be a bit tricky:
1: a causal editor might that wants to have some periodicality information for each limb to show possible logical throw/catch times
2: reconstruction of some high-level notation from a given JIF (not too important in my opinion)
Any more use cases?

With reasonable input precision and some assumptions (for example denominator <= 10) both will be fine, as the co's explanation and the heuristic from Adrian show.

If really needed we could still add some information into the limb definition. Like "this limb is using thirds" or something.


Another possibility to solve this is by multiplying the bpm (beats per minute) value with the lowest common multiple of the denomitators.
This way, we end up only having integer values (except when using irrational numbers).

Adrian suggested that the time unit should always refer to two-handed patterns. This allows to have a reasonable bpm default, so it does not need to be
set when its not important (it's probably only important when we have some exact timing needs like an audio file or light props programming).
I like this idea.
Keeping that would mean we need a global bpm setting with reasonable default and a global speed factor (like 3 for using thirds) with 1 as default.



BTW:
I'm perfectly fine having "time" as a reference to timestamps and "duration" for durations. I think most programming libraries have the naming that like that.
Using "beat" suggests that fractions are not allowed. Even when we decide to be able to set a global speed factor and have the logical throws/catches on integer
times, we would still have fractions for dwell times and for the possibility of using irrational numbers.

Cheers
Christian

JaCo Stuifbergen

unread,
Oct 26, 2020, 10:06:34 AM10/26/20
to juggling-interchange-format
I copy some suggestions by Christian from a different thread:
Another possibility to solve this is by multiplying the bpm (beats per minute) value with the lowest common multiple of the
denominators.
I am happy with this solution.

Adrian suggested that the time unit should always refer to two-handed patterns. This allows to have a reasonable bpm default

Keeping that would mean we need a global bpm setting with reasonable default and a global speed factor (like 3 for using thirds) with 1 as default.
So BPM_actual = BPM_default * speedFactor.
I would prefer just a BPM setting with a reasonable default.

For club passing, my BPM is around 130. For ball juggling, it is higher, perhaps 180.

But I don't mind if software uses a BPM of 13.000 or a million for calculations.

Florian Pesth

unread,
Nov 2, 2020, 2:58:14 PM11/2/20
to juggling-inte...@googlegroups.com
Hi Christian,

Am Mon, 26 Oct 2020 12:57:04 +0100
schrieb Christian Helbling <he...@helch.ch>:

>
> I agree with Adrian here and just go with floating point numbers for
> simplicity. I think all the use cases on lukas' list are doable fine
> with them.
>
> I see the following two use-cases where it could be a bit tricky:
> 1: a causal editor might that wants to have some periodicality
> information for each limb to show possible logical throw/catch times

Yes. One thing that also comes to mind is "branching". We could allow
to store different variants of throws from a certain beat (i.e. you
could juggle "531" at this point or "441"). But this should probably go
into a later version of the standard.

> 2: reconstruction of some high-level notation from a given JIF (not
> too important in my opinion) Any more use cases?

I think 2 is an important use case as it increases the attractiveness
of JIF a lot. If it is easy to use JIF as a native format for any
juggling program people will do so.

Look for example at the MealMaster format (a format to store cooking
recipes). The original program is pretty much dead but there are still
a lot of programs supporting it and whole usenet groups using it all
the time. And that format was never specified ;).

>
> With reasonable input precision and some assumptions (for example
> denominator <= 10) both will be fine, as the co's explanation and the
> heuristic from Adrian show.

If we go for full multiples we don't need the heuristics. If we use the
heuristics we would need to specify the precision (but - as noted - we
can just use full multiples).

>
> If really needed we could still add some information into the limb
> definition. Like "this limb is using thirds" or something.

This was my original idea with the beatgroups. But there are newer
posts on this topic :).

>
>
> Another possibility to solve this is by multiplying the bpm (beats
> per minute) value with the lowest common multiple of the
> denomitators. This way, we end up only having integer values (except
> when using irrational numbers).

Indeed, this is good.

>
> Adrian suggested that the time unit should always refer to two-handed
> patterns.

I would be careful with that. Who is to say that two hands is normal? It
is assumed with vanilla siteswap but even a single juggler can bounce a
ball on his head while juggling with two hands and this would already
make three limbs.


> This allows to have a reasonable bpm default, so it does
> not need to be set when its not important (it's probably only
> important when we have some exact timing needs like an audio file or
> light props programming). I like this idea. Keeping that would mean
> we need a global bpm setting with reasonable default and a global
> speed factor (like 3 for using thirds) with 1 as default.

I don't like the idea of a default BPM as it is pretty random.

>
>
>
> BTW:
> I'm perfectly fine having "time" as a reference to timestamps and
> "duration" for durations. I think most programming libraries have the
> naming that like that. Using "beat" suggests that fractions are not
> allowed. Even when we decide to be able to set a global speed factor
> and have the logical throws/catches on integer times, we would still
> have fractions for dwell times and for the possibility of using
> irrational numbers.

I would distinguish between "causal numbers" and real absolute time
marks. Causal numbers can be converted into an absolute time by an BPM
factor (or some SI unit factor). But if I want to write 531 I might
not want to specify an absolute time - I think we should allow the
programs to store as much or as less information as they want in a
reasonable way.

Cheers,
Florian

>
> Cheers
> Christian
>

Christian Helbling

unread,
Nov 2, 2020, 5:06:53 PM11/2/20
to juggling-inte...@googlegroups.com
On 02.11.20 20:58, Florian Pesth wrote:
> Hi Christian,
>
> Am Mon, 26 Oct 2020 12:57:04 +0100
> schrieb Christian Helbling <he...@helch.ch>:
>
>>
>> I agree with Adrian here and just go with floating point numbers for
>> simplicity. I think all the use cases on lukas' list are doable fine
>> with them.
>>
>> I see the following two use-cases where it could be a bit tricky:
>> 1: a causal editor might that wants to have some periodicality
>> information for each limb to show possible logical throw/catch times
>
> Yes. One thing that also comes to mind is "branching". We could allow
> to store different variants of throws from a certain beat (i.e. you
> could juggle "531" at this point or "441"). But this should probably go
> into a later version of the standard.
Interesting.
I agree to postpone that.

I don't think floating point numbers would interfere with such a feature in any way.
I'd imagine solving this one by splitting up the throws into throw sequences
(something like code blocks in compilers), and linking them with branching instrutions.

By the way:
I thought about introducing loops for cases like excited siteswaps.
For example
5 [741] 3
or
[4] 5 [741] 3 [4]

An animator would then need to provide some kind of user interface to exit from some
loop or have some configuration how many times to stay in a loop. The same would apply
to choose branches.

I think both use-cases could be solved by one mechanism.
But not now :)

>> 2: reconstruction of some high-level notation from a given JIF (not
>> too important in my opinion) Any more use cases?
>
> I think 2 is an important use case as it increases the attractiveness
> of JIF a lot. If it is easy to use JIF as a native format for any
> juggling program people will do so.
As jif is much more expressive and detailed, going from jif back to some
high-level notation is not always possible.
But we can try to facilitate it to some degree.

> Look for example at the MealMaster format (a format to store cooking
> recipes). The original program is pretty much dead but there are still
> a lot of programs supporting it and whole usenet groups using it all
> the time. And that format was never specified ;).
With that argument, I should go ahead and create/use my own format in passist
that people will adopt; without trying to find consensus on a clean specification (-:C


Cheers
Christian

Reply all
Reply to author
Forward
0 new messages