HOW COMPUTERS CAST STRINGS TO NUMBERS

Поделиться
HTML-код
  • Опубликовано: 24 ноя 2024

Комментарии • 219

  • @jannegrey
    @jannegrey 4 месяца назад +86

    Funnily at 10:10 there might be a mistake - because the number "1 0000 111 0000" after adding "00000 111" lengthens to "1 0000 111 00 111", so it "feels" like there is additional 0 between 2 triples of "1". And it doesn't feel like we needed to expand due to number being too big (256,512 - we are in between). But I didn't have the time to check it.

    • @CoreDumpped
      @CoreDumpped  4 месяца назад +44

      Yeah, somehow that 0 got in between. I didn't noticed this while editing so thanks. I'll pin this comment.

    • @CoreDumpped
      @CoreDumpped  4 месяца назад +65

      Somebody else also noticed that the condition in the C version of the algorithm is wrong.
      `str[i] < '0' && str[i] > '9'` will always return false, since it's checking if str[i] < 48 and str[i] > 57, which is never true. The condition should be `str[i] < '0' || str[i] > '9'`
      My apologies for these mistakes.

    • @zionmelson7936
      @zionmelson7936 4 месяца назад

      your byte format sucks bruv 😐

    • @jannegrey
      @jannegrey 4 месяца назад +5

      @@zionmelson7936 I was formatting 1 and 0 separately, so one could see there was additional number there. I didn't go for actual formatting like it should be.

    • @twqzjsidIsndusiakdixisqjeksixi
      @twqzjsidIsndusiakdixisqjeksixi 4 месяца назад +3

      @@CoreDumpped No worries, Core. Programming is hard.

  • @paulosouza449
    @paulosouza449 4 месяца назад +186

    This channel is criminally underrrated. This is top tier content for free

    • @JesusPlsSaveMe
      @JesusPlsSaveMe 4 месяца назад +3

      To everyone in this chat, Jesus is calling you today. Come to him, repent from your sins, bear his cross and live the victorious life

    • @CritickalTvRandom
      @CritickalTvRandom 4 месяца назад +1

      Toda la maldita razón del mundo, amigo

    • @justsomeordinarykid923
      @justsomeordinarykid923 3 месяца назад

      @@JesusPlsSaveMewe got people glazing Jesus before gta 6

  • @dkub3522
    @dkub3522 4 месяца назад +106

    "And on this channel, we hate black boxes."
    *subscribed*

  • @rcnhsuailsnyfiue2
    @rcnhsuailsnyfiue2 16 дней назад +2

    Please can you make a video on bitshifting and bitmasking? I assumed bitshifting would be used for this, but your explanation of the algorithm here was excellent. Thanks!

  • @ava3a13
    @ava3a13 4 месяца назад +43

    While on the topic, I know it's a bit early for the channel to explain it now, but whenever you get to architectures, please don't forget endianness explanation, there are always explanations of how but not of why. Great video as always!!

    • @CoreDumpped
      @CoreDumpped  4 месяца назад +27

      Yeah, there is a video about endianness already on the list.

    • @marcuswilliams3455
      @marcuswilliams3455 4 месяца назад +1

      Ah, that Little Endian vs Big Endian discussion. ;)

    • @jack4x3
      @jack4x3 4 месяца назад +1

      There is simply no why, computing machines should exist in one of the ways. Either one is a choice

  • @xOWSLA
    @xOWSLA 4 месяца назад +63

    It's funny that right now at my job, I am dealing with serializing ASCII characters and you are making this video. I'm really glad I'm here George. Nicely done.

    • @GoldbergToastyBred
      @GoldbergToastyBred 4 месяца назад

      im learning c and tried to do i kind of failed and after that he makes that video

    • @vladsiaev12
      @vladsiaev12 4 месяца назад

      how did you send a comment 6 hours before the video uploaded?

    • @PennyEvolus
      @PennyEvolus 4 месяца назад

      ​@@vladsiaev12they pay for early access

    • @rebecasally
      @rebecasally 4 месяца назад

      ​@@vladsiaev12 probably a member of the channel

  • @oglothenerd
    @oglothenerd 4 месяца назад +21

    A video on how computers represent negative and floating numbers. That would be amazing!

    • @JesusPlsSaveMe
      @JesusPlsSaveMe 4 месяца назад

      Jesus is the only way to salvation and to the father.
      Please repent today and turn away from your sins yo escape judgement 🙏🙏 There is no other way to get to the father but through him.

    • @oglothenerd
      @oglothenerd 4 месяца назад +7

      @@JesusPlsSaveMe I cannot tell if this is a funny way of saying that my idea is insane, or if this is genuinely an ad for Christianity.

    • @xM0nsterFr3ak
      @xM0nsterFr3ak 3 месяца назад +2

      For negative numbers look into 2-compliment and for floating point number look into IEEE 754

    • @oglothenerd
      @oglothenerd 3 месяца назад +2

      @@xM0nsterFr3ak I figured out the basics, but a video on how that stuff is actually dealt with in the CPU would be amazing!

    • @logickin
      @logickin 20 дней назад

      ​@@oglothenerd Negative integers are simple. Like @M0sterFr3ak mentioned, it is 2-compliment which you need to find the binary representation of the number (for example, for a 8 bit number 10, its binary representation is 00001010). With the binary representation, all you need to do is to invert all the bits (from 00001010 to 11110101) and to add one at the LSB (from 11110101 to 11110110), than you will have -10.

  • @smallcube-zn2mm
    @smallcube-zn2mm 4 месяца назад +5

    Another way to do:
    1. Take the string as argument
    2. Access every character
    3. Use fixed values with switch cases for every character till '0' to '9'
    like
    switch(str[i])
    case '1' : 001
    4. Do bit shifting to create a BCD value containing all characters
    5. Convert BCD to binary
    6. return binary
    It may or may not be faster

    • @trapfethen
      @trapfethen 4 месяца назад

      Once you get into SIMD instruction extensions, then a plethora of performance optimizations become available to you.

  • @adityavs18
    @adityavs18 4 месяца назад +13

    Amazing. I’m literally addicted to learning like this through your videos. They’re awesome ! I can’t wait for the next one and yes I would love a video on conversion of the binary values back do string to understand how the print function works !

  • @sunpacplussoftware5948
    @sunpacplussoftware5948 2 месяца назад +1

    This is an excellently planned out documentary. The planning and wit required to explain ASCII conversions and binary maths is excellent. And what a great narrative voice too!

  • @madelinew2884
    @madelinew2884 3 месяца назад +1

    I'm really happy I found this channel... I somewhat knew how it worked, but this just makes it really clear. You are great at explaining things. I am eagerly waiting for more videos

  • @kossboss
    @kossboss 4 месяца назад +1

    Person reveal. Your a young lad. One of those prodigies I keep hearing about.

  • @user-nk7tb6qg3v
    @user-nk7tb6qg3v 4 месяца назад +5

    I love channels that demystify these things
    tks

  • @anonymous0x0
    @anonymous0x0 4 месяца назад +4

    This channel is pure gold.

  • @thibaut5345
    @thibaut5345 4 месяца назад +14

    This is not casting, this is converting. Casting is a grammatical operation (forcing the compiler to think that a data has a certain type, but not actually doing any conversation).

    • @Nicoder6884
      @Nicoder6884 3 месяца назад +2

      Casting sometimes requires conversion.
      “10” - 2 in JavaScript both casts *and* converts “10” into 10 in order to return 8

  • @yueni_bizzare_simp
    @yueni_bizzare_simp 23 дня назад

    6:57 who doesn't understand how it works, look for binary arithmetics.
    Basically binary arithmetic addition follow the next steps:
    1. 0 + 0 = 0
    2. 0 + 1 = 1
    3. 1 + 0 = 0 with carry 1 (one will be used for the addition of bit on next radix - number that is on the left side from one we were looking at)
    4. 1 + 1 = 0 with carry 1
    5. 1 + 1 + 1 = 1 with carry 1

  • @patrick8613
    @patrick8613 4 месяца назад +2

    I talked to my colleagues about this exact problem, specifically the one you mentioned in the end, great video!

  • @mrdj6450
    @mrdj6450 4 месяца назад

    From now i respect my computer, doing this all process within micro seconds...
    Thanks for the best video...

  • @AntonioZL
    @AntonioZL 4 месяца назад +6

    Not the topic I expected after the last videos, but still a very welcome one.

  • @shmuel6
    @shmuel6 4 месяца назад

    You my friend have done the impossible. You have actually made programming make sense.

  • @HkRines
    @HkRines 4 месяца назад +1

    0:07 Yes... Just yes. Maybe this will be SUPER slow but yes)
    I have this in mind:
    1. Represent each character in string with 4-bit binary number (Using Unicode)
    2. Make BCD number from all characters
    3. Convert BCD to binary.
    Now you have a number.
    For example:
    "532"
    1. || "5" = 0101 || 3 = 0011 || 2 = 0010 ||
    2. 0101 0011 0010
    (BCD to Binary algorithm)
    3. "532" = 1000010100
    __________
    Now I'll watch video)
    ----------------------------------
    Ps. Subtracting 48 is a very cleaver solution!! Now we can do same thing as i did.
    But initially i just wanted use table to store Unicode and number like this:
    | Unicode Number | Number in Binary |
    And use this table to convert each symbol to a number but yeah we can just subtract '0' encoding to get a number!

  • @windowhand
    @windowhand 3 месяца назад +1

    Just want to say that you are the one i was searching for. You answers same questions as mines and in a way that i wanted. Hope you would get more known

  • @swordoman2158
    @swordoman2158 4 месяца назад

    When it gets to converting decimal fractions as strings to floats things get a lot more complicated. Looking forward to seeing a new video about this case in the future!

  • @brielov
    @brielov 4 месяца назад +1

    This is the way. Would love to see a performant way to do the same with floating points numbers. This kind of video is what I really like to watch.

    • @cyrilemeka6987
      @cyrilemeka6987 4 месяца назад

      Using IEEE-754 binary floating point 32 or 64 format, you would have to manually decode the floating point. First bitcast the floating point to an unsigned integer of the same size, I.e float -> ui32 or double -> ui64, then using the encoding specification you extract the sign, exponent and mantissa from the integer.

  • @mghost7737
    @mghost7737 Месяц назад +1

    One of the best channels, hands down!

  • @cornevanzyl5880
    @cornevanzyl5880 4 месяца назад

    This is so well explained, I don't think I'll ever be able to forget this.

  • @Garfield_Minecraft
    @Garfield_Minecraft 3 месяца назад +1

    This is actually easy how I would think
    Since "0" is 48 we subtract 48 from it get the real value first then multiplying to the correct power of 10. So once the number is inputted "1234" turn them to binary 1 10 11 100 and multiply and adding(but computer does to know what index number to start with which isn't so hard) and we get the number before input another number. These process happened really fast we cannot notice them

  • @Garfield_Minecraft
    @Garfield_Minecraft 3 месяца назад +1

    This is actually easy how I would think
    Since "0" is 48 we subtract 48 from it get the real value first then multiplying to the correct power of 10. So once the number is inputted "1234" turn them to binary 1 10 11 100 and multiply and adding(but computer does to know what index number to start with which isn't so hard) and we get the number before input another number. These process happened really fast we cannot notice them
    I mean we can even start backwards just tell it(computer) how long the number is ourselves but that means we have to know tell the length parameter so that way is better

  • @olhoTron
    @olhoTron 4 месяца назад

    I work on a php application where someone in the past reimplemented the string to number conversion...
    And if you have questions...
    Yes, it involved a loop with a bunch of ifs to check each digit
    Yes, they messed it up
    Yes, changing the usages of the function to "(int)$value" fixed a lot of bugs
    Yes, the person who did it (acording to git blame) still works there but was promoted to manager
    No, we dont do code reviews or anything like that

  • @ndrea417
    @ndrea417 2 месяца назад +1

    11:04 in the if you wirte &&(and) instead of ||(or). Great video!

  • @merveilleskatumba2886
    @merveilleskatumba2886 3 месяца назад

    The way I agree
    This channel is very underrated

  • @verysadboyo7424
    @verysadboyo7424 4 месяца назад +3

    I can sleep in peace now, I had exactly this question today and yes chair I was looking for double w.

  • @morzatt
    @morzatt 4 месяца назад

    Great video! I would really like to see a video explaining the problem with null values inside languages and how to avoid them, that would be very educative!

  • @Pwnification
    @Pwnification 4 месяца назад

    This channel is perfect to watch alongside taking CS50 to start my programming journey. Pretty excited about understanding everything in this video and learning more. Thanks for the quality videos.

  • @atzefatze
    @atzefatze 4 месяца назад +3

    11:50 ...yes please! :)

  • @danielrhouck
    @danielrhouck 4 месяца назад

    I would like a future video about converting an int to a string, but I am more interested in the much more complicated process of converting a float to a string.

  • @marcuswilliams3455
    @marcuswilliams3455 4 месяца назад

    Great, that's a perfect illustration of what happens internally with the atoi() function. Ah, I noticed there is minor difference between converting a numeric string to a binary integer vs converting a numeric string to a BCD number. And that is multiplying by 10 vs shifting by 4 bits (since BCD numbers represents each numeric digit every 4 bits).
    I find it rather interesting, with the IBM mainframe, existing a single machine instruction (CVD) which can convert a numeric string (up to 31 digits) to BCD number. Likewise, there's another instruction (CVB) which can convert these BCD number into integers.

  • @ruhollahh01
    @ruhollahh01 4 месяца назад +1

    great job thank you
    i would love an explanation about formatting numbers into strings as well!

  • @abhilasha4334
    @abhilasha4334 4 месяца назад

    Yes we need that too and don't forget to upload the remaining part of cpu episode

  • @eliasepg
    @eliasepg 4 месяца назад

    It reminds me about the college times! I really like this stuff, thank you!

  • @robelbelay4065
    @robelbelay4065 3 месяца назад

    Beautiful explanation, especially if that code at the end. Thank you very much

  • @dera_ng
    @dera_ng Месяц назад +1

    Goldfield casually existing on RUclips 😮‍💨

  • @electrolyteorb
    @electrolyteorb 4 месяца назад

    your AI voice is fine. dont change it... GOLD content as always!

  • @timschulz9563
    @timschulz9563 4 месяца назад

    ASCII allows for the use of a bitmask to get the number itself. The probably preferred way to convert these BCD numbers to an integer is reverse double dabble. There's a wiki article about it. This algorithm gets rid of expensive and area intensive (depending on your architecture, first for CPU, second for FPGA/custom silicon) multiplications and relies on fast/small shifts and add/sub operations.

  • @jannegrey
    @jannegrey 4 месяца назад +1

    Another video! I'm glad I checked your channel, since there was no notification. Typical of RUclips sadly. Though it probably has to do with delay between the last part and this video. RUclips deprioritizes notifications if you normally have 1 week cadence and then suddenly release video month later. Honestly being a RUclipsr is a ton of work.

  • @waynehawkins654
    @waynehawkins654 4 месяца назад

    Nice, I will show my class this. Well explained.

  • @aitanapalomanespardos7089
    @aitanapalomanespardos7089 Месяц назад +1

    I would love to see the video about the reverse algorithm!

  • @1kvolt1978
    @1kvolt1978 4 месяца назад +1

    Well, actually, there is a limit for integer numbers (as well as float), at least in C. And there is also negative numbers. So the more proper function is a little bit more complex.
    I wrote mine like this:
    int64_t StrToNum(char *Str) {
    int64_t Result = 0;
    uint32_t Index = 0;
    bool IsNegative = false;
    if (Str[0] == '-') {
    IsNegative = true;
    Index = 1;
    }
    while ((Str[Index] != '\0') && (Str[Index] >= '0') && (Str[Index]

  • @utilizadorable
    @utilizadorable 4 месяца назад

    Great video, as always. Got me curious to understand how the process works with negative numbers.

  • @Zensi123
    @Zensi123 4 месяца назад +2

    Hi, thanks for this video. What tools do you use for your animations? They are amazing.

  • @oguz_new
    @oguz_new 2 месяца назад

    very powerful explanation. thanks jhon

  • @Nick-ex4tk
    @Nick-ex4tk 4 месяца назад

    My man your videos are awesome. Can you do an explanation on how the clock is used to move the process forward from the transistor level? For example, how do transistor gates use the clock to take the next instruction into the instruction register at the right time?

  • @diadetediotedio6918
    @diadetediotedio6918 4 месяца назад

    Before watching the response, this was the algorithm I came up with:
    ```
    base = 10
    str = "1030"
    println(string_to_int(str, base))
    fn string_to_int(str: string, base: int) {
    let number = 0
    each (index, char) of str {
    let digit = lookup_from(char)
    let exp = base ** len(str) - index - 1
    number += digit * exp
    }
    return number
    }
    ```

  • @lordkauck
    @lordkauck 4 месяца назад +1

    literally Str(number) - 0x30 for 0-9, Str(uppercase letter) - 0x41 for A-Z, Str(lowercase)-0x61 for a-z
    Converting between the two is as simple as
    char(lower) = char(upper) ^ 0x20

  • @kunalchakraborty9735
    @kunalchakraborty9735 4 месяца назад +16

    Revolutionary idea of getting the actual number

  • @luislanga
    @luislanga 4 месяца назад

    Thank God I never thought about this before I saw the title of this video

  • @aldomaresca9994
    @aldomaresca9994 4 месяца назад

    dude, youre going to the moon, and i'm liking your videos all the way there

  • @knkootbaoat6759
    @knkootbaoat6759 4 месяца назад

    please do explain the process from getting from an integer to "string"/output. Keep up the great work!

  • @Jack-do3sy
    @Jack-do3sy 4 месяца назад

    Man I love this channel so much, this would've been so helpful back when I was learning to do this kinda stuff lol

  • @TheFacal
    @TheFacal 4 месяца назад

    Thank you so much, this was a question I had from some time ago. I would love to see the continuation of this video :)

  • @Milan____
    @Milan____ 4 месяца назад

    "Shipping to Alaska, Hawaii, Puerto Rico, and International addresses is currently not available." -> pity I was actually looking for a new chair
    Anyway, good video, it's nice to see easier topics now and then.

  • @lfoevuf340
    @lfoevuf340 4 месяца назад

    How to convert a number to a string: The key instrument is integer division. Let's consider the number 4327. Dividing by 10 we obtain 432 and remainder 7. Now, we already know how to convert a single digit to its corresponding ASCII code: just add 48 or ord('0'). So in this one step we obtained the so called least significant digit (7) and are left with 432. Now, we just have to repeat the same procedure until we are left with no more digits (when the last division yields 0 as the quotient).
    PS: Integer division is just a single processor instruction and actually gives both the quotient and the remainder in one go so it's pretty fast.

  • @dj.yacine
    @dj.yacine 4 месяца назад +2

    Always high quality content 😊

  • @talwald1680
    @talwald1680 4 месяца назад

    Great video, and it is a very introductory version of the algorithm. However, this is not an efficient algorithm. The reason is due to the fact that the alu can't parallelize the multiplications and the additions. You should see Andrei Alexandrescu's lecture on this! But this can be a cool continuation of this video.

    • @CoreDumpped
      @CoreDumpped  4 месяца назад +1

      Thanks for the advice, I'll take a look at the lecture as soon as I get some free time. I'm assuming it is related to SIMD but if not I'm sure I'll enjoy it anyways.

  • @thaivo666
    @thaivo666 4 месяца назад

    Can you make a video about how to virtual memory works in OS? Thanks a lot. All of your videos are so useful.

  • @portalwalker_
    @portalwalker_ 3 месяца назад

    I think it's more intuitive to multiply the numbers by magnitudes of 10 first and then adding them up. After that the better algorithm that you showed in the video would've been more clear I think

  • @somerhaha1687
    @somerhaha1687 4 месяца назад

    I had to learn this when making my own programming language and i wish i had found this video sooner .-.

  • @cryptociva
    @cryptociva 3 месяца назад

    Your videos are a blessing!

  • @jbond5834
    @jbond5834 4 месяца назад

    the sequential method in the video also solve the issue ,when the input string is like '0987''

  • @NinosYoukhana
    @NinosYoukhana 4 месяца назад

    Amazing! Thank you very much for doing this!

  • @valcubeto
    @valcubeto 4 месяца назад

    Underrated channel

  • @CybernetonPL
    @CybernetonPL 4 месяца назад +1

    11:55 spoiler, it's the double dabble. Look for Sebastian lagues visualizing data with displays video

  • @MickeyToler-ye9ds
    @MickeyToler-ye9ds 4 месяца назад

    I would like you to explain and give an example of the end process that you asked about.

  • @revolutionarydefeatism
    @revolutionarydefeatism 2 месяца назад

    Please create a video explaining how CPUs handle floating-point numbers.

  • @yuseidrex
    @yuseidrex 4 месяца назад +1

    this channel is really good!

  • @dnoldGames
    @dnoldGames Месяц назад

    Thats an amazing video, I was just wondering how that would work with negative numbers?

  • @AbhijitGangoly
    @AbhijitGangoly 4 месяца назад

    Please make a video about the reverse function, Binary to Numerical String.

  • @mdyousufgazi4030
    @mdyousufgazi4030 3 месяца назад

    epic explanation

  • @pepemanolo69
    @pepemanolo69 4 месяца назад

    Subscribed, wanna see the second part

  • @RaphaelOkai
    @RaphaelOkai 4 месяца назад

    This is just soo beautiful. 😍

  • @helmytaufik6735
    @helmytaufik6735 4 месяца назад

    Arigatouu keep em coming 🔥🔥🔥

  • @TWPO
    @TWPO 4 месяца назад

    Simply awesome

  • @noritesc5000
    @noritesc5000 4 месяца назад

    done the string to float double and it myself
    but a different approach
    stuff skiped in this video
    - Sign of a value
    for applaing a Sign
    multyplay output value by -1 if the '-' is found at the start of a string
    - decimal parsing
    the same way as string to int
    but
    - do it 2 times
    and when . was found instead of multiplying value just divide decimal it by 10 for each Ituretion
    and cheak if value is not to large

  • @umertariq6706
    @umertariq6706 28 дней назад

    I really appreciate your videos. They answer a lot of the questions that stuck in my mind.
    I have another confusion related to streams and buffer in C language. The unusual behavior of scanf when it encounter new lines charactor(
    ). Can you please make a video on streams?

  • @wikbar13
    @wikbar13 2 месяца назад

    Good content, please keep it up!

  • @centerfield6339
    @centerfield6339 Месяц назад

    The C robustness check should have an || not an &&, and the Python one will raise a ValueError if the digit is between "2" and "8". And it doesn't need a f-string.
    Also, I wonder how much electricity we'd have saved globally if 0-9 were binary 0-9.

  • @blackhorse8422
    @blackhorse8422 4 месяца назад

    Please make a video about big and little endianness, I always forget the order and don't understand the order of bits itself in comparison to the byte order.

  • @Andremzsptm
    @Andremzsptm 4 месяца назад +1

    Great content as always!

  • @ТеодорТодоров-н2к
    @ТеодорТодоров-н2к 4 месяца назад

    Please please do a video explaining operating system

  • @laoluade5741
    @laoluade5741 3 месяца назад

    I would love to see an explanation for thr reverse!

  • @Nathan00at78Uuiu
    @Nathan00at78Uuiu 2 месяца назад

    i saw the primeagen on the screen there. neat.

  • @oscarmendez9079
    @oscarmendez9079 4 месяца назад

    Thanks again for this amazing content

  • @mohsenzare2511
    @mohsenzare2511 4 месяца назад

    Thanks for your video

  • @marcopinedo2368
    @marcopinedo2368 4 месяца назад

    I'm guessing that in order to convert an integer to a string you have to make reverse process. Instead of multiplying you have to divide the number, take the reminder and add '0'

  • @anon_y_mousse
    @anon_y_mousse 4 месяца назад

    I've always found it rather beautiful that ASCII encodes decimal characters as 0x30 to 0x39 in hex, so mentally you can just remove 0x3 and know what the number is.

  • @Germisstucklmao
    @Germisstucklmao 4 месяца назад

    Here's my solution in Nim (python like language that compiles to C/C++/Js/objective-c):
    proc stringToUInt32(input: string): uint32 = #proc is used instead of def
    let ord0 = ord('0')
    var multiple: uint32 = 1
    var final: uint32 = 0
    for i in countDown(input.len - 1, 0): #going from the end of the string to the beginning
    final += multiple * uint32(ord(input[i]) - ord0) # Cast to uint32
    multiple *= 10
    return final
    var x = stringToUInt32("52")
    echo x #output: 52
    Anyways the other (smart) people's solutions probably work better

  • @StevenHokins
    @StevenHokins 4 месяца назад

    Nicely done, thank you ❤

  • @flv-hd7nn
    @flv-hd7nn 4 месяца назад +1

    please continue>

  • @mirror.creativity
    @mirror.creativity 2 месяца назад

    This is masterclass. Can you please share your ressoures oder some book to read?

  • @User-ty2ml
    @User-ty2ml 4 месяца назад

    Beautiful!!!! Thanks