Discuss Scratch

jmdzti_0-0
Scratcher
1000+ posts

Scratch Workaround Guide VII

_nix wrote:

~snip~
you spelt my username wrong in a quote

The_Cool_Scratch_Guy wrote:

jmdzti_0-0 wrote:

so, uh… for the power with the log method, negative bases don’t work like that. ~snip~

_nix wrote:

~snip~

ispretty wrote:

~snip~

I literally just fixed that. Just scroll up about 6 posts.

Edit: even though negative bases and fractional exponents give imaginary numbers that it doesn't give, it does give the same results as Google's calc
thank you for the fix (i’m just gonna ignore you used google’s calc as a comparison)

getting the imaginary and real part is possible, but it rewquires a lot of scripting and i’m too lazy to do it.
jmdzti_0-0
Scratcher
1000+ posts

Scratch Workaround Guide VII

jmdzti_0-0 wrote:

_nix wrote:

~snip~
you spelt my username wrong in a quote

The_Cool_Scratch_Guy wrote:

jmdzti_0-0 wrote:

so, uh… for the power with the log method, negative bases don’t work like that. ~snip~

_nix wrote:

~snip~

ispretty wrote:

~snip~

I literally just fixed that. Just scroll up about 6 posts.

Edit: even though negative bases and fractional exponents give imaginary numbers that it doesn't give, it does give the same results as Google's calc
thank you for the fix (i’m just gonna ignore you used google’s calc as a comparison)

getting the imaginary and real part is possible, but it rewquires a lot of scripting and i’m too lazy to do it.

(IN RADIANS) assuming both parts of the exponentiation are real

formula for real part of a power aˣ:

formula for imaginary part of a power aˣ:

if anyone wants to code it, it is possible.

Last edited by jmdzti_0-0 (April 29, 2025 08:32:02)

_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

Alright! Is this the workaround for exponents please!

We need a review

Did we get it right?

We worked off of @The_Cool_Scratch_Guy's workaround posted earlier. But I think the even/odd there was flipped, because it was coming out negative for like, -4^2 “=” -16. We also had to use a branching if/else to support, like… positive numbers lol. But we needed to use if/else anyway, to filter out non-integer negative exponents.

Alsooooo

jmdzti_0-0 wrote:

you spelt my username wrong in a quote
SORRY

ispretty wrote:

_nix wrote:

jmdzti_0-0 wrote:

so, uh… for the power with the log method, negative bases don’t work like that. For instance, (-5)² is not -25, but rather 25 (you can calculate this manually), opposed to what the output says.
You're right. I really wonder where that came from, since it's literally “accounted for” as though that *is* how they work, even though… it obviously isn't.

if <(base ::custom-arg) < (0)> then
set [power v] to ((-1) * (power)) // Whyyyy???
end
That's because you're putting a negative number into a logarithm, which outputs a complex number. Also, this isn't a good fix, as now (-2)² = -4 when it should be equal to 4. There needs to be a check to see if the exponent is even or odd (see this Scratch Wiki article) for more info.
I mean yeah we knew that. Like. Obviously “this isn't a good fix”, we were just quoting the workaround we'd included in the guide. That's why the “Whyyyy???” is there, it means we were like shaking our head at ourselves, trying to figure out how on earth this code even happened in the first place.

ispretty wrote:

Also, this workaround means that (-27)^(1/3) is equal to NaN, which is perfectly acceptable depending on your definition of a root (real root versus first principal root).
Yeah I think that's the intended like, scope limitation, here. If we wanted the real root we really should be outputting ±3 instead of 3, for, like, 27^(1/3), but obviously that would be annoying. Or we could have “positive root” and “negative root” variables and the consuming code could work with those, but that's also really clunky and unnecessary. like at that point just implement complex numbers lol
ispretty
Scratcher
500+ posts

Scratch Workaround Guide VII

_nix wrote:

Alright! Is this the workaround for exponents please!

We need a review

Did we get it right?
Looks good

_nix wrote:

ispretty wrote:

Also, this workaround means that (-27)^(1/3) is equal to NaN, which is perfectly acceptable depending on your definition of a root (real root versus first principal root).
Yeah I think that's the intended like, scope limitation, here. If we wanted the real root we really should be outputting ±3 instead of 3, for, like, 27^(1/3), but obviously that would be annoying. Or we could have “positive root” and “negative root” variables and the consuming code could work with those, but that's also really clunky and unnecessary. like at that point just implement complex numbers lol
-3 isn't a solution to x^3=-27; there are negative and positive pairs of solutions only when the power is even.

Last edited by ispretty (April 28, 2025 13:32:08)

_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

ispretty wrote:

_nix wrote:

ispretty wrote:

Also, this workaround means that (-27)^(1/3) is equal to NaN, which is perfectly acceptable depending on your definition of a root (real root versus first principal root).
Yeah I think that's the intended like, scope limitation, here. If we wanted the real root we really should be outputting ±3 instead of 3, for, like, 27^(1/3), but obviously that would be annoying. Or we could have “positive root” and “negative root” variables and the consuming code could work with those, but that's also really clunky and unnecessary. like at that point just implement complex numbers lol
-3 isn't a solution to x^3=-27; there are negative and positive pairs of solutions only when the power is even.
wdym, I'd love a slightly deeper explanation to this? because obviously just manually computing (-3)(-3)(-3) = -27, so why doesn't this “count” as a solution?

also oh okay I kinda get it but like
no
the… the problem isn't that “-3 isn't a solution to x^3=-27”, it's that “-3 isn't a solution to x^3=27” POSITIVE 27 lol, the expression I specified, so yeah. the problem isn't that I don't get it, it's that I picked a bad example. “we should be outputting ±4 instead of 4 for 64^(1/3)” would have been to the effect I intended.

edit november 2025: hijacking this post as a footnote/addendum for a later post

as best i can tell, although both blocks do wait 1/30sec (see above test), the pitch effect applies immediately while the volume effect is delayed. in the pictured script both “set pitch effect” and “set volume to” happen on the same frame (verified this). you hear no “pop” of the sound changing from pitch 0 to pitch 100, but you do hear the sound at all for a moment, despite “set volume to 0” being run on the same frame. this mostly just confirms what nembence was saying and verifies the “set volume” block

please note that broadcasts cause the receiving scripts to evaluate on the next frame (read: at the start of the following 1/30th sec), but if the broadcast is not “broadcast and wait”, then the broadcast block itself is instantaneous (does not cause any delay in any way). “start sound” is exactly the same way and so if you test this script for yourself, it does not matter the order you put “start sound” and “broadcast”. one more measurement predictably shows zero time has passed (image). i was speaking from experience here. the statement about broadcast delaying one “frame” is almost true. however, i was failing to measure it. broadcast doesn't actually delay one frame, it delays one yield. if there is any motion occurring in the project then that means delaying a frame. in this simple example, there was no motion, so the yield took zero seconds. i was not measuring the delay of the broadcast, i was measuring the delay of the pitch and volume blocks. this matters for later because in the “frames of offset” breakdown i will assume “when I receive” takes one frame to actually respond.

i am assuming the effect of “set volume” occurs at exactly the end of the frame. the real delay may be only part of a frame. we've verified it is not more than a frame, at least, since “set volume to 0 -> set pitch to 100” doesn't give you an instant of squeaky audio pop. safari on mac.

because the effect of “set volume” is delayed it must be run before “set pitch”, not on the same frame. for this reason in my proposed updated workaround i am just having them in the same script, which is run off-thread, in a “when I receive” block. also because i would like the workaround to be portable and usable in multiple sprites at once, i am using a for-this-sprite-only variable to control responding to the broadcast.

i explain the reasoning for the number of frames of offset (zero) i chose below the script. i started with zero and attempted to explain why zero is or is not correct. didn't make it to the end, so this “zero” is still basically a placeholder. the script shown is unedited, from before i tried to explain any of my thinking.

to be honest i am personally unconvinced “wait…seconds” is actually inaccurate. if it suffices for a “wait # of frames” then the waiting part really can just be “wait 1/8 * time seconds”

define skip (time) seconds of audio
set [audio command v] to [fast-forward] // for this sprite only
broadcast [process audio command v]
repeat ((30) * (((1)/(8)) * (time))) // "repeat" does a Math.round() for us
wait (0) seconds
end
set [audio command v] to [restore]
broadcast [process audio command v]

when I receive [process audio command v]
if <(audio command) = [fast-forward]> then
set [audio command v] to [none] // it's important this happens right away
set volume to (0) %
set [pitch v] effect to (360)
end

when I receive [process audio command v] // it's important these are separate scripts
if <(audio command) = [restore]> then
set [audio command v] to [none]
set [pitch v] effect to (0)
set volume to (100) % // you could restore to "old volume", "old pitch effect" here
end

reasoning for frames of offset:
  1. we take “skip 4 seconds of audio” to mean "delay the shortest amount of time possible so that when this block is done running, audio playback will be aligned to the moment that is 4 seconds later than when I started running this block, and I can hear it"

  2. it takes 2 frames 3 frames to reach “set pitch effect to 360”. that means for 2 frames 3 frames no changes in speed have occurred. this would be unavoidable even without the broadcast setup. (the broadcast setup actually only offers clarity for the exact number of frames waited, which is explicit instead of implicit. it also affects timings because there is a yield before “when I receive” runs, which i assume lasts one frame.) so far, 2/30sec 3/30sec of audio have naturally passed, at the default playback rate (we assume it is 1x speed).

  3. we must wait 2 frames 3 frames at the end of script evaluation in order to reach “set volume to 100%”, to satisfy “and I can hear it”. this is where i stopped typing initially, because i realized why broadcasts were just making the situation more complex. as a result, please pretend the rest of my explanation is in red.

    the first of these frames is at 8x speed because “when I receive” takes one frame to actually begin evaluating (assuming there is motion in the rest of the project). it's only one frame at 8x speed because “set pitch effect” itself takes effect as soon as it is run. however, there is then one frame of delay from “set pitch”, and then one frame of delay (assumed) before “set volume” takes effect, for a total fo 3 frames waiting after the command to set volume is sent.

    going back to heck: well we've finally reached the same conclusion that nembence did. if “set pitch effect to 0” takes effect at start of frame and “set volume to 100” takes effect at the end of frame, then they can happen during the same frame, as long as you can't hear it. it's not viable at the start but it is viable when restoring.

  4. we are not constrained on the total number of frames we must wait. a goal is to delay “the shortest amount of time possible”.

dropping the addendum here, mostly because the real working script would be very different from the one we're working off, and we cannot neatly integrate the final timings back into it

Last edited by _nix (Nov. 3, 2025 14:21:32)

ispretty
Scratcher
500+ posts

Scratch Workaround Guide VII

_nix wrote:

ispretty wrote:

_nix wrote:

ispretty wrote:

Also, this workaround means that (-27)^(1/3) is equal to NaN, which is perfectly acceptable depending on your definition of a root (real root versus first principal root).
Yeah I think that's the intended like, scope limitation, here. If we wanted the real root we really should be outputting ±3 instead of 3, for, like, 27^(1/3), but obviously that would be annoying. Or we could have “positive root” and “negative root” variables and the consuming code could work with those, but that's also really clunky and unnecessary. like at that point just implement complex numbers lol
-3 isn't a solution to x^3=-27; there are negative and positive pairs of solutions only when the power is even.
wdym, I'd love a slightly deeper explanation to this? because obviously just manually computing (-3)(-3)(-3) = -27, so why doesn't this “count” as a solution?

also oh okay I kinda get it but like
no
the… the problem isn't that “-3 isn't a solution to x^3=-27”, it's that “-3 isn't a solution to x^3=27” POSITIVE 27 lol, the expression I specified, so yeah. the problem isn't that I don't get it, it's that I picked a bad example. “we should be outputting ±4 instead of 4 for 64^(1/3)” would have been to the effect I intended.
oops, yes I did mean -3 isn't a solution to x^3=27
jmdzti_0-0
Scratcher
1000+ posts

Scratch Workaround Guide VII

_nix wrote:

ispretty wrote:

_nix wrote:

ispretty wrote:

Also, this workaround means that (-27)^(1/3) is equal to NaN, which is perfectly acceptable depending on your definition of a root (real root versus first principal root).
Yeah I think that's the intended like, scope limitation, here. If we wanted the real root we really should be outputting ±3 instead of 3, for, like, 27^(1/3), but obviously that would be annoying. Or we could have “positive root” and “negative root” variables and the consuming code could work with those, but that's also really clunky and unnecessary. like at that point just implement complex numbers lol
-3 isn't a solution to x^3=-27; there are negative and positive pairs of solutions only when the power is even.
wdym, I'd love a slightly deeper explanation to this? because obviously just manually computing (-3)(-3)(-3) = -27, so why doesn't this “count” as a solution?

also oh okay I kinda get it but like
no
the… the problem isn't that “-3 isn't a solution to x^3=-27”, it's that “-3 isn't a solution to x^3=27” POSITIVE 27 lol, the expression I specified, so yeah. the problem isn't that I don't get it, it's that I picked a bad example. “we should be outputting ±4 instead of 4 for 64^(1/3)” would have been to the effect I intended.
I mean, yes, roots are sometimes written with a ±, but I don’t think it’s that necessary. Apart from breaking the number input, you can always just either add a plus-minus yourself with a join block, or flip signs if needed.
WsDanzel
Scratcher
56 posts

Scratch Workaround Guide VII

Anyone has idea
delete this sprite :: looks
and
set loud to () :: sound
The_Cool_Scratch_Guy
Scratcher
100+ posts

Scratch Workaround Guide VII

_nix wrote:

But I think the even/odd there was flipped, because it was coming out negative for like, -4^2 “=” -16. We also had to use a branching if/else to support, like… positive numbers lol.
Actually, you could just modify the boolean as shown below. That was a mistake on my part, I was rushing a bit. And yes, it was flipped.

([10^  v] of ((exponent) * ([log v] of ([abs v] of(base)::operators)) :: operators) :: operators) * (((2)*<<((exponent)mod(2))=(0)> or < (base) > (0) >>)-(1))
The_Cool_Scratch_Guy
Scratcher
100+ posts

Scratch Workaround Guide VII

jmdzti_0-0 wrote:

(IN RADIANS) assuming both parts of the exponentiation are real

formula for real part of a power aˣ:

formula for imaginary part of a power aˣ:

if anyone wants to code it, it is possible.

Game on…
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

The_Cool_Scratch_Guy wrote:

_nix wrote:

But I think the even/odd there was flipped, because it was coming out negative for like, -4^2 “=” -16. We also had to use a branching if/else to support, like… positive numbers lol.
Actually, you could just modify the boolean as shown below. That was a mistake on my part, I was rushing a bit. And yes, it was flipped.
Ah, good point, thanks. I… wish that scratchblocks scrolled on the forums lol, it's really hard to incorporate nice wide scripts.

Actually yeah, HYPOTHETICALLY, here's a version that doesn't use multiplication-by-boolean at all. Also an excuse to write it in scratchblocks because groan. (oh wait yeah apple502j's tool exists thank youuuuu)

define raise (base) to the power of (exponent)
if <<(base) > (0)> or <(base) = (0)>> then
set [power result v] to ([10 ^ v] of ((exponent) * ([log v] of (base))))
else
if <(exponent) = (round (exponent))> then
set [power result v] to ([10 ^ v] of ((exponent) * ([log v] of ([abs v] of (base)))))
if <((exponent) mod (2)) = (1)> then
set [power result v] to ((-1) * (exponent))
end
else
set [power result v] to ((0) / (0))
end
end

No wait wait! Stuff in common! Let's try this:

define raise (base) to the power of (exponent)
if <<(base) < (0)> and <not <(exponent) = (round (exponent))>>> then
set [power result v] to ((0) / (0)) // This outputs NaN because...
stop [this script v] // ...raising a negative base to a fraction gives a complex number.
end
set [power result v] to ([10 ^ v] of ((exponent) * ([log v] of ([abs v] of (base)))))
if <<(base) < (0)> and <((exponent) mod (2)) = (1)>> then
set [power result v] to ((-1) * (power result))
end

Can I get a review on this one, too I think it's a lot easier to read and understand, and still not too clunky. If it's good, then it's probably the final version going into the workaround guide. (NB: We have not reviewed whatever the completely different existing method is, and we should do that too.)
The_Cool_Scratch_Guy
Scratcher
100+ posts

Scratch Workaround Guide VII

_nix wrote:

Ah, good point, thanks. I… wish that scratchblocks scrolled on the forums lol, it's really hard to incorporate nice wide scripts.
~snip~

You could shift + arrow keys

Also I'm going to attempt to use the formula to incorporate complex numbers
ispretty
Scratcher
500+ posts

Scratch Workaround Guide VII

_nix wrote:

The_Cool_Scratch_Guy wrote:

_nix wrote:

But I think the even/odd there was flipped, because it was coming out negative for like, -4^2 “=” -16. We also had to use a branching if/else to support, like… positive numbers lol.
Actually, you could just modify the boolean as shown below. That was a mistake on my part, I was rushing a bit. And yes, it was flipped.
Ah, good point, thanks. I… wish that scratchblocks scrolled on the forums lol, it's really hard to incorporate nice wide scripts.

Actually yeah, HYPOTHETICALLY, here's a version that doesn't use multiplication-by-boolean at all. Also an excuse to write it in scratchblocks because groan. (oh wait yeah apple502j's tool exists thank youuuuu)

define raise (base) to the power of (exponent)
if <<(base) > (0)> or <(base) = (0)>> then
set [power result v] to ([10 ^ v] of ((exponent) * ([log v] of (base))))
else
if <(exponent) = (round (exponent))> then
set [power result v] to ([10 ^ v] of ((exponent) * ([log v] of ([abs v] of (base)))))
if <((exponent) mod (2)) = (1)> then
set [power result v] to ((-1) * (exponent))
end
else
set [power result v] to ((0) / (0))
end
end

No wait wait! Stuff in common! Let's try this:

define raise (base) to the power of (exponent)
if <<(base) < (0)> and <not <(exponent) = (round (exponent))>>> then
set [power result v] to ((0) / (0)) // This outputs NaN because...
stop [this script v] // ...raising a negative base to a fraction gives a complex number.
end
set [power result v] to ([10 ^ v] of ((exponent) * ([log v] of ([abs v] of (base)))))
if <<(base) < (0)> and <((exponent) mod (2)) = (1)>> then
set [power result v] to ((-1) * (power result))
end

Can I get a review on this one, too I think it's a lot easier to read and understand, and still not too clunky. If it's good, then it's probably the final version going into the workaround guide. (NB: We have not reviewed whatever the completely different existing method is, and we should do that too.)
A comment for the negation would be nice. Maybe something like this but make the comment shorter:
if <<(base) < (0)> and <((exponent) mod (2)) = (1)>> then // if the base is negative
set [power result v] to ((-1) * (power result)) // we need to negate the result on when the exponent is odd, as the negative is cancelled when the exponent is even
end
Other than that, it looks good
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

ispretty wrote:

A comment for the negation would be nice. Maybe something like this but make the comment shorter:

if <<(base :: custom-arg) < (0)> and <((exponent :: custom-arg) mod (2)) = (1)>> then // if the base is negative
set [power result v] to ((-1) * (power result)) // we need to negate the result on when the exponent is odd, as the negative is cancelled when the exponent is even
end

Other than that, it looks good
Thanks
How about this?

if <<(base :: custom-arg) < (0)> and <((exponent :: custom-arg) mod (2)) = (1)>> then // If we're raising a negative base to an odd exponent...
set [power result v] to ((-1) * (power result)) // ...we need to make the result negative, since the negatives *don't* cancel out.
end

or maybe we'll just explain it a little more explicitly in the text describing this method haha
Bitebite12
Scratcher
1000+ posts

Scratch Workaround Guide VII

Congrats on sticky! (may or may not be 2 years late)
ispretty
Scratcher
500+ posts

Scratch Workaround Guide VII

_nix wrote:

ispretty wrote:

A comment for the negation would be nice. Maybe something like this but make the comment shorter:

if <<(base :: custom-arg) < (0)> and <((exponent :: custom-arg) mod (2)) = (1)>> then // if the base is negative
set [power result v] to ((-1) * (power result)) // we need to negate the result on when the exponent is odd, as the negative is cancelled when the exponent is even
end

Other than that, it looks good
Thanks
How about this?

if <<(base :: custom-arg) < (0)> and <((exponent :: custom-arg) mod (2)) = (1)>> then // If we're raising a negative base to an odd exponent...
set [power result v] to ((-1) * (power result)) // ...we need to make the result negative, since the negatives *don't* cancel out.
end

or maybe we'll just explain it a little more explicitly in the text describing this method haha
I think that's good, but the final call's up to you
ExcitedDuckVienna
Scratcher
98 posts

Scratch Workaround Guide VII

This guide feels a little… dead.

Are you still willing to keep updating this forum?
_nix
Scratcher
1000+ posts

Scratch Workaround Guide VII

ExcitedDuckVienna wrote:

This guide feels a little… dead.

Are you still willing to keep updating this forum?
Probably not much. Last time we tried to hand it off the person had disappeared by the time we told them they got the guide, though, and didn't really come back. No shame intended, it's just a thing that happened. We haven't really been interested in “re-opening” applications since.

But no, our interest in maintaining the guide is obviously too fleeting for much of anything to get done. On the rare occasion that we honestly have space in our life, we just put it toward other stuff. So I guess that answers your question? I'm not “opening” it to a “takeover” either though, because the formal process is a pain in the knees.

I guess if you have better ideas for the future of the thread, go for it, but right now our worry is that whoever runs it next is gonna disappear off of Scratch within frankly a year or so. Most people do. We would rather have feedback from people who really use the workaround guide than from those who want to make it, and, sorry, but no one really comments that they like or dislike this guide. So it is difficult to feel that updating it is worth very much.

We totally want to believe in a resource like this existing as good as it possibly can just for its own sake, but we don't find that as motivating as we did years ago… I mean, we do believe in it, but it doesn't drive us so much. (Mostly because we put that drive into aspects of other projects.) I think all guides are a little bit doomed to that fate, so ideally whoever would take it over next is going to have the same motivation we did when we started out. But it can dry up quick, so IDK, maybe consider opening to the next round of takeovers way, way sooner than we did. Right?

Anyway, if someone can demonstrate that they want to improve the guide because they think it has identifiable problems that they personally want to fix, then let us know, and that will probably convince us.
GarbagePanda
Scratcher
100+ posts

Scratch Workaround Guide VII

Thank you! This is very useful!
secretuch
Scratcher
500+ posts

Scratch Workaround Guide VII

Bump

Powered by DjangoBB