• AVR Freaks

Hot!32 Bit multiplication with PIC

Page: 12 > Showing page 1 of 2
Author
BEsmart
Starting Member
  • Total Posts : 37
  • Reward points : 0
  • Joined: 2019/04/26 06:47:36
  • Location: 0
  • Status: offline
2019/10/20 05:29:08 (permalink)
0

32 Bit multiplication with PIC

I know this seems to be a silly question and I also never had problems like this with AVR before...
I'm using an uint_32 variable for a timing intervall counter, but the result of the multiplication seem to be weird, if the number gets too big ... but still way beyond the limit of unsigned 32 bit ( 4294967295 ).
 
 #include "stdint.h"
//...
//...
   uint32_t intervall;
   intervall = 8 * 5000;
// -> leads to 40000   => OK!!
 
    intervall = 18 * 5000;
// -> leads to 24464   => !!???

 
I've been debugging this value with measuring an IO-Pin and also with printing it to UART.
The value of 24464 seem really to be the result of the multplication.
 
What am I missing???
Many thanks!
#1

26 Replies Related Threads

    bitdoctor
    Starting Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/10/11 06:10:09
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 05:32:38 (permalink)
    0
    You're missing the code that shows us how you use the result and print it.
    Edit - constant expression arithmetic in C is done with int arithmetic, the product is 90,000 which exceeds the size of an int. You need:
    intervall = 18UL * 5000;

    That's also true in AVR land.
    post edited by bitdoctor - 2019/10/20 05:46:17
    #2
    BEsmart
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2019/04/26 06:47:36
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 06:04:14 (permalink)
    0
    I also tried
    intervall = 18UL * 5000;

    and even
    intervall = 18UL * 5000UL;

    still leads to 24464 .
    Debugged with IO-Pin and sprintf (outstring , "%s%u" , intervall)...
     
    #3
    bitdoctor
    Starting Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/10/11 06:10:09
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 06:14:36 (permalink)
    +1 (1)
    Why didn't you tell us that? Anyway, the %u specifier is for an unsigned int, not an unsigned long int. Try %ul.
    #4
    BEsmart
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2019/04/26 06:47:36
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 06:24:03 (permalink)
    0
    ...OK.
    Using %ul only leads to 24464l displayed and still not affecting the time intervall on th IO-Port, where the value is meaured as intervall in ms. So it is easy to see, if the value is correct.
    #5
    bitdoctor
    Starting Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2019/10/11 06:10:09
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 06:27:43 (permalink)
    0
    Then post the entire code. Nobody can guess everything you're doing. The number 24464 is the result of the overflow (truncation) of 90,000 which is 90000-2^16, so the general observation that it's an unsigned int overflow is certain.
    post edited by bitdoctor - 2019/10/20 06:46:52
    #6
    BEsmart
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2019/04/26 06:47:36
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 06:46:59 (permalink)
    0
    Unfortunately the complete code is quite large and this is the only problem I have.
    Is it maybe a complier setup problem with XC8?
    #7
    NorthGuy
    Super Member
    • Total Posts : 5754
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: online
    Re: 32 Bit multiplication with PIC 2019/10/20 06:56:33 (permalink)
    +2 (2)
    BEsmart
    ...OK.
    Using %ul only leads to 24464l displayed and still not affecting the time intervall on th IO-Port, where the value is meaured as intervall in ms. So it is easy to see, if the value is correct.



    It is %lu not %ul.
    #8
    pcbbc
    Super Member
    • Total Posts : 1373
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 06:56:49 (permalink)
    +1 (1)
    No it’s a truncation to a 16-bit int as previously described.
    If the entire project is too big, post a minimum sample project which demonstrates your problem.
    #9
    BEsmart
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2019/04/26 06:47:36
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 07:09:36 (permalink)
    0
    OK, I'll do that
    #10
    1and0
    Access is Denied
    • Total Posts : 9899
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 11:40:56 (permalink)
    +1 (1)
    %ul will print 24464l
    %lu will print 90000
    Smile: Smile
    #11
    BEsmart
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2019/04/26 06:47:36
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 13:04:51 (permalink)
    0
    ...yes, that's true! ;-)
    But still multiplication is weird:
    uint32_t intervall;
     
    intervall = 90000;
    sprintf (outstring , "%s%lu" , intervall) displays: 90000 -> OK!

    intervall = 40000 + 50000;
    sprintf (outstring , "%s%lu" , intervall) displays: 90000 -> OK!

    intervall = 8 * 5000;
    sprintf (outstring , "%s%lu" , intervall) displays: 24464 -> weird!!!

    btw. I'm using a PIC18LF46K42 and XC8 2.10   
    #12
    1and0
    Access is Denied
    • Total Posts : 9899
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 13:23:23 (permalink)
    +1 (1)
    BEsmart
    But still multiplication is weird:
    uint32_t intervall;
     
     
     
    intervall = 8 * 5000;
    sprintf (outstring , "%s%lu" , intervall) displays: 24464 -> weird!!!

    btw. I'm using a PIC18LF46K42 and XC8 2.10   

    8 is an int and 5000 is int, so the multiplication is performed using 16-bit with a result of an int which is 16-bit; i.e. the result will be truncated to 16-bit.  So use 32-bit multiplication, that is at least one of the operand must be 32-bit, such as 8UL which is a long.
    post edited by 1and0 - 2019/10/20 13:25:26
    #13
    JPortici
    Super Member
    • Total Posts : 820
    • Reward points : 0
    • Joined: 2012/11/17 06:27:45
    • Location: Grappaland
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 13:24:31 (permalink)
    +2 (2)
    please someone correct me.
     
    case 1: hard coded constant doesn't fit in a signed int (16 bit), compiler will use longs (32bit) for calculations
    case 2: at least one of hard coded constants in the operation doesn't fit in a signed int, so compiler will use longs for calculations
    case 3: both operands fit in a signed int, compiler will use signed ints for the result.
    #14
    1and0
    Access is Denied
    • Total Posts : 9899
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 13:26:17 (permalink)
    +1 (1)
    Jack_M
    please someone correct me.
     
    case 1: hard coded constant doesn't fit in a signed int (16 bit), compiler will use longs (32bit) for calculations
    case 2: at least one of hard coded constants in the operation doesn't fit in a signed int, so compiler will use longs for calculations
    case 3: both operands fit in a signed int, compiler will use signed ints for the result.

    Yes, yes, yes; and then the result is converted to unsigned long by the = operator.
    post edited by 1and0 - 2019/10/20 13:28:40
    #15
    NorthGuy
    Super Member
    • Total Posts : 5754
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: online
    Re: 32 Bit multiplication with PIC 2019/10/20 13:56:15 (permalink)
    0
    Jack_M
    case 2: at least one of hard coded constants in the operation doesn't fit in a signed int, so compiler will use longs for calculations



    Yes, 50000 has "long int" type. All decimal constants are signed. However, since C99, a hexadecimal constant (such as 0xc350, which is seemingly the same) may be unsigned and will be "unsigned int" if it fits into int. So, "40000 + 50000" would produce a result different from "0x9c40 + 0xc350".
     
    #16
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11407
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 14:21:33 (permalink)
    0
    All decimal constants are signed.

     
    In C90, an unsuffixed decimal constant can be "unsigned long".
     
    #17
    1and0
    Access is Denied
    • Total Posts : 9899
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 14:37:14 (permalink)
    0
    … because C90 does not have long long int. ;)
    #18
    BEsmart
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2019/04/26 06:47:36
    • Location: 0
    • Status: offline
    Re: 32 Bit multiplication with PIC 2019/10/20 15:08:46 (permalink)
    0
    ...you are rigth! :-)
    Everything works fine, if one of the operators is unsigned long.
    intervall = 18 * 5000UL;
    sprintf (outstring , "%s%lu" , intervall) displays: 90000  -> Now OK!

    intervall = 18UL * 5000;
    sprintf (outstring , "%s%lu" , intervall) displays: 90000  -> Now OK!

    uint32_t number_1;
    number_1 = 18;
    intervall =  number_1 * 5000;     
    sprintf (outstring , "%s%lu" , intervall) displays: 90000  -> Now OK!

    uint8_t number_1;
    number_1 = 18;
    intervall = (uint32_t) number_1 * 5000;     
    sprintf (outstring , "%s%lu" , intervall) displays: 90000  -> Now OK!

    Many Thanks!!
     
    #19
    ric
    Super Member
    • Total Posts : 24278
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: 32 Bit multiplication with PIC 2019/10/20 16:00:08 (permalink)
    +1 (1)
    This is the usual confusion when people have learnt C on a 32 bit machine, then change to an 8 bit machine without adjusting their assumptions. :)
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5